Isis 3.0 Programmer Reference
Back | Home
MeasureTool.cpp
1 #include "IsisDebug.h"
2 #include "MeasureTool.h"
3 
4 #include <QApplication>
5 #include <QCheckBox>
6 #include <QFileDialog>
7 #include <QHBoxLayout>
8 #include <QLineEdit>
9 #include <QMenu>
10 #include <QMenuBar>
11 #include <QMessageBox>
12 #include <QStackedWidget>
13 #include <QStatusBar>
14 #include <QTableWidget>
15 #include <QToolButton>
16 
17 #include <geos/geom/Geometry.h>
18 #include <geos/geom/Point.h>
19 
20 #include "Camera.h"
21 #include "Distance.h"
22 #include "FileName.h"
23 #include "Latitude.h"
24 #include "Longitude.h"
25 #include "MdiCubeViewport.h"
26 #include "Projection.h"
27 #include "RingPlaneProjection.h"
28 #include "TProjection.h"
29 #include "SurfacePoint.h"
30 #include "ToolPad.h"
31 
32 namespace Isis {
39  MeasureTool::MeasureTool(QWidget *parent) : Tool(parent) {
40  m_rubberBand = NULL;
41  m_tableWin = new TableMainWindow("Measurements", parent);
43 
44  // Create the action for showing the table
45  m_action = new QAction(parent);
46  m_action->setText("Measuring ...");
47 
48  connect(m_action, SIGNAL(triggered()), m_tableWin, SLOT(showTable()));
49  connect(m_action, SIGNAL(triggered()), m_tableWin, SLOT(raise()));
50  connect(m_action, SIGNAL(triggered()), m_tableWin, SLOT(syncColumns()));
51  //m_tableWin->installEventFilter(this);
52 
53  m_tableWin->addToTable(false, "Feature\nName", "Feature Name");
54  m_tableWin->addToTable(false, "Feature\nType", "Feature Type");
55  m_tableWin->addToTable(true,
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, "Segments Sum\nkm", "Segments Sum", -1, Qt::Horizontal, "Sum of Segment lengths in kilometers");
69  m_tableWin->addToTable(false, "Segment Number", "Segment Number", -1, Qt::Horizontal, "Segment number of a segmented line");
70  m_tableWin->addToTable(false, "Path", "Path");
71  m_tableWin->addToTable(false, "FileName", "FileName");
72  m_tableWin->addToTable(false, "Notes", "Notes");
73 
74  m_tableWin->setStatusMessage("Click, Drag, and Release to Measure a Line");
75 
76  addRow();
77  }
78 
79 
89  QAction *action = new QAction(toolpad);
90  action->setIcon(QPixmap(toolIconDir() + "/measure.png"));
91  action->setToolTip("Measure (M)");
92  action->setShortcut(Qt::Key_M);
93 
94  QString text =
95  "<b>Function:</b> Measure features in active viewport \
96  <p><b>Shortcut:</b> M</p> ";
97  action->setWhatsThis(text);
98 
99  return action;
100  }
101 
102 
111  QWidget *MeasureTool::createToolBarWidget(QStackedWidget *parent) {
112  QWidget *hbox = new QWidget(parent);
113  QToolButton *measureButton = new QToolButton(hbox);
114  measureButton->setText("Table");
115  measureButton->setToolTip("Record Measurement Data in Table");
116  QString text =
117  "<b>Function:</b> This button will bring up a table that will record the \
118  starting and ending points of the line, along with the distance between \
119  the two points on the image. To measure the distance between two points, \
120  click on the first point and releasing the mouse at the second point. \
121  <p><b>Shortcut:</b> CTRL+M</p>";
122  measureButton->setWhatsThis(text);
123  measureButton->setShortcut(Qt::CTRL + Qt::Key_M);
124  connect(measureButton, SIGNAL(clicked()), m_tableWin, SLOT(showTable()));
125  connect(measureButton, SIGNAL(clicked()), m_tableWin, SLOT(syncColumns()));
126  connect(measureButton, SIGNAL(clicked()), m_tableWin, SLOT(raise()));
127  measureButton->setEnabled(true);
128 
129  m_rubberBand = new RubberBandComboBox(this,
138  RubberBandComboBox::Line // default
139  );
140 
141  m_distLineEdit = new QLineEdit(hbox);
142  m_distLineEdit->setText("");
143  m_distLineEdit->setMaxLength(12);
144  m_distLineEdit->setToolTip("Line Length");
145  QString text2 = "<b>Function: </b> Shows the length of the line drawn on \
146  the image.";
147  m_distLineEdit->setWhatsThis(text2);
148  m_distLineEdit->setReadOnly(true);
149 
150  m_showAllSegments = new QCheckBox(hbox);
151  m_showAllSegments->setText("Show All Segments");
152 
153  m_unitsComboBox = new QComboBox(hbox);
154  m_unitsComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
155 
156  miComboUnit = -1;
157 
159  connect(m_unitsComboBox, SIGNAL(activated(int)), this, SLOT(updateDistEdit()));
160  connect(rubberBandTool(), SIGNAL(modeChanged()), this, SLOT(updateUnitsCombo()));
161 
162  QHBoxLayout *layout = new QHBoxLayout(hbox);
163  layout->setMargin(0);
164  layout->addWidget(m_rubberBand);
165  layout->addWidget(m_distLineEdit);
166  layout->addWidget(m_unitsComboBox);
167  layout->addWidget(measureButton);
168  layout->addWidget(m_showAllSegments);
169  layout->addStretch(1);
170  hbox->setLayout(layout);
171  return hbox;
172  }
173 
174 
180  // get the previous index if not initializing
181  if (miComboUnit >= 0) {
182  miComboUnit = m_unitsComboBox->currentIndex();
183  }
184 
185  m_unitsComboBox->clear();
186  m_showAllSegments->setEnabled(false);
187 
188  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
189  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
190 
191  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
192  m_showAllSegments->setEnabled(true);
193  }
194 
195  m_unitsComboBox->addItem("km");
196  m_unitsComboBox->addItem("m");
197  m_unitsComboBox->addItem("pixels");
198  if (miComboUnit < 0 || miComboUnit > 2) { // default && error checking
199  miComboUnit = 2;
200  }
201  }
202  else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
203  m_unitsComboBox->addItem("degrees");
204  m_unitsComboBox->addItem("radians");
205  if (miComboUnit > 1 || miComboUnit < 0) { // default && error checking
206  miComboUnit = 0;
207  }
208  }
209  else {
210  m_unitsComboBox->addItem("km^2");
211  m_unitsComboBox->addItem("m^2");
212  m_unitsComboBox->addItem("pix^2");
213  if (miComboUnit < 0 || miComboUnit > 2) { // default && error checking
214  miComboUnit = 2;
215  }
216  }
217 
218  m_unitsComboBox->setCurrentIndex(miComboUnit);
219  }
220 
221 
228  void MeasureTool::addTo(QMenu *menu) {
229  menu->addAction(m_action);
230  }
231 
232 
238  MdiCubeViewport *cvp = cubeViewport();
239  MdiCubeViewport *d;
240  m_numLinked = 0;
241 
242  int currentRow = m_tableWin->currentRow();
243 
244  while (currentRow >= m_tableWin->table()->rowCount()) {
245  addRow();
246  }
247 
248  if (cvp == NULL) {
250  }
251  else {
252  updateDist(cvp, currentRow);
253  m_tableWin->table()->selectRow(currentRow);
254 
255  if (cvp->isLinked()) {
256  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
257  d = (*(cubeViewportList()))[i];
258 
259  if (d->isLinked() && d != cvp) {
260  m_numLinked++;
261 
262  if (currentRow + m_numLinked >= m_tableWin->table()->rowCount()) {
263  addRow();
264  }
265 
266  updateDist(d, currentRow + m_numLinked);
267  }
268  }
269  }
270  }
271  }
272 
273 
279  updateMeasure();
280 
281  if (rubberBandTool()->currentMode() != RubberBandTool::AngleMode && m_unitsComboBox->currentIndex() != 2) {
282  if (cubeViewport()->camera() == NULL && cubeViewport()->projection() == NULL) {
283  QMessageBox::information((QWidget *)parent(), "Error",
284  "File must have a Camera Model or Projection to measure in km or m");
285  return;
286  }
287  }
288 
289  if (!m_tableWin->table()->isVisible()) return;
290  if (m_tableWin->table()->item(m_tableWin->currentRow(), StartLineIndex)->text() == "N/A" &&
291  m_tableWin->table()->item(m_tableWin->currentRow(), AngleDegIndex)->text() == "N/A" &&
292  m_tableWin->table()->item(m_tableWin->currentRow(), AreaPixIndex)->text() == "N/A") return;
293 
294  addRow();
295  m_tableWin->setCurrentRow(m_tableWin->table()->rowCount() - 1);
296 
297  QApplication::sendPostedEvents(m_tableWin->table(), 0);
298  }
299 
300 
306  //m_tableWin->clearRow(m_tableWin->currentRow());
307  }
308 
309 
315  if (m_rubberBand) {
316  m_rubberBand->reset();
317  rubberBandTool()->setDrawActiveViewportOnly(false);
318  }
319  }
320 
321 
329  void MeasureTool::updateRow(int row) {
330  ASSERT(row < m_tableWin->table()->rowCount());
331 
332  if (row >= m_tableWin->table()->rowCount()) {
333  return;
334  }
335 
336  // Blank out the row to remove stuff left over from previous cvps
337  for (int c = 0; c < m_tableWin->table()->columnCount(); c++) {
338  m_tableWin->table()->item(row, c)->setText("");
339  }
340 
341  // Write all the new info to the current row
342  if (m_startLat != Null && m_startLon != Null) {
343  m_tableWin->table()->item(row, StartLatIndex)->setText(QString::number(m_startLat));
344  m_tableWin->table()->item(row, StartLonIndex)->setText(QString::number(m_startLon));
345  }
346  else {
347  m_tableWin->table()->item(row, StartLatIndex)->setText("N/A");
348  m_tableWin->table()->item(row, StartLonIndex)->setText("N/A");
349  }
350 
351  if (m_endLat != Null && m_endLon != Null) {
352  m_tableWin->table()->item(row, EndLatIndex)->setText(QString::number(m_endLat));
353  m_tableWin->table()->item(row, EndLonIndex)->setText(QString::number(m_endLon));
354  }
355  else {
356  m_tableWin->table()->item(row, EndLatIndex)->setText("N/A");
357  m_tableWin->table()->item(row, EndLonIndex)->setText("N/A");
358  }
359 
360  if (m_mDist != Null && m_kmDist != Null) {
361  m_tableWin->table()->item(row, DistanceMIndex)->setText(QString::number(m_mDist));
362  m_tableWin->table()->item(row, DistanceKmIndex)->setText(QString::number(m_kmDist));
363  }
364  else {
365  m_tableWin->table()->item(row, DistanceKmIndex)->setText("N/A");
366  m_tableWin->table()->item(row, DistanceMIndex)->setText("N/A");
367  }
368 
369  if (m_degAngle != Null && m_radAngle != Null) {
370  m_tableWin->table()->item(row, AngleDegIndex)->setText(QString::number(m_degAngle));
371  m_tableWin->table()->item(row, AngleRadIndex)->setText(QString::number(m_radAngle));
372  }
373  else {
374  m_tableWin->table()->item(row, AngleDegIndex)->setText("N/A");
375  m_tableWin->table()->item(row, AngleRadIndex)->setText("N/A");
376  }
377 
378  if (m_startSamp != Null && m_startLine != Null) {
379  m_tableWin->table()->item(row, StartSampIndex)->setText(QString::number(m_startSamp));
380  m_tableWin->table()->item(row, StartLineIndex)->setText(QString::number(m_startLine));
381  }
382  else {
383  m_tableWin->table()->item(row, StartSampIndex)->setText("N/A");
384  m_tableWin->table()->item(row, StartLineIndex)->setText("N/A");
385  }
386 
387  if (m_endSamp != Null && m_endLine != Null) {
388  m_tableWin->table()->item(row, EndSampIndex)->setText(QString::number(m_endSamp));
389  m_tableWin->table()->item(row, EndLineIndex)->setText(QString::number(m_endLine));
390  m_tableWin->table()->item(row, DistancePixIndex)->setText(QString::number(m_pixDist));
391  }
392  else {
393  m_tableWin->table()->item(row, EndSampIndex)->setText("N/A");
394  m_tableWin->table()->item(row, EndLineIndex)->setText("N/A");
395  m_tableWin->table()->item(row, DistancePixIndex)->setText("N/A");
396  }
397 
398  if (m_pixArea != Null) {
399  m_tableWin->table()->item(row, AreaPixIndex)->setText(QString::number(m_pixArea));
400  }
401  else {
402  m_tableWin->table()->item(row, AreaPixIndex)->setText("N/A");
403  }
404 
405  if (m_mArea != Null) {
406  m_tableWin->table()->item(row, AreaKmIndex)->setText(QString::number(m_kmArea));
407  m_tableWin->table()->item(row, AreaMIndex)->setText(QString::number(m_mArea));
408  }
409  else {
410  m_tableWin->table()->item(row, AreaKmIndex)->setText("N/A");
411  m_tableWin->table()->item(row, AreaMIndex)->setText("N/A");
412  }
413 
414  m_tableWin->table()->item(row, PathIndex)->setText(m_path);
415  m_tableWin->table()->item(row, FileNameIndex)->setText(m_fname);
416  }
417 
418 
419 
427  void MeasureTool::updateRows(int row) {
428  int requiredRows = m_distanceSegments.size() + row;
429  int rowDiff = (int)(requiredRows - m_tableWin->table()->rowCount());
430 
431  //Make sure we have all the necessary rows and items in each table cell.
432  if (requiredRows > m_tableWin->table()->rowCount()) {
433  for (int r = 0; r < rowDiff; r++) {
434  addRow();
435  }
436  }
437 
438  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode &&
439  m_distanceSegments.size() > 0) {
440  double distanceSum = 0;
441  for (int i = 0; i < m_distanceSegments.size(); i++) {
442  //write a new row for each segment...
443  if (m_startLatSegments[i] != Null && m_startLonSegments[i] != Null) {
444  m_tableWin->table()->item(row + i, StartLatIndex)->setText(QString::number(m_startLatSegments[i]));
445  m_tableWin->table()->item(row + i, StartLonIndex)->setText(QString::number(m_startLonSegments[i]));
446  }
447  else {
448  m_tableWin->table()->item(row + i, StartLatIndex)->setText("N/A");
449  m_tableWin->table()->item(row + i, StartLonIndex)->setText("N/A");
450  }
451 
452  if (m_endLatSegments[i] != Null && m_endLonSegments[i] != Null) {
453  m_tableWin->table()->item(row + i, EndLatIndex)->setText(QString::number(m_endLatSegments[i]));
454  m_tableWin->table()->item(row + i, EndLonIndex)->setText(QString::number(m_endLonSegments[i]));
455  }
456  else {
457  m_tableWin->table()->item(row + i, EndLatIndex)->setText("N/A");
458  m_tableWin->table()->item(row + i, EndLonIndex)->setText("N/A");
459  }
460 
461  if (m_startSampSegments[i] != Null && m_startLineSegments[i] != Null) {
462  m_tableWin->table()->item(row + i, StartSampIndex)->setText(QString::number(m_startSampSegments[i]));
463  m_tableWin->table()->item(row + i, StartLineIndex)->setText(QString::number(m_startLineSegments[i]));
464  }
465  else {
466  m_tableWin->table()->item(row + i, StartSampIndex)->setText("N/A");
467  m_tableWin->table()->item(row + i, StartLineIndex)->setText("N/A");
468  }
469 
470  if (m_endSampSegments[i] != Null && m_endLineSegments[i] != Null) {
471  m_tableWin->table()->item(row + i, EndSampIndex)->setText(QString::number(m_endSampSegments[i]));
472  m_tableWin->table()->item(row + i, EndLineIndex)->setText(QString::number(m_endLineSegments[i]));
473  }
474  else {
475  m_tableWin->table()->item(row + i, EndSampIndex)->setText("N/A");
476  m_tableWin->table()->item(row + i, EndLineIndex)->setText("N/A");
477  }
478 
479  if (m_pixDistSegments[i] != Null) {
480  m_tableWin->table()->item(row + i, DistancePixIndex)->setText(QString::number(m_pixDistSegments[i]));
481  }
482  else {
483  m_tableWin->table()->item(row + i, DistancePixIndex)->setText("N/A");
484  }
485 
486  if (m_distanceSegments[i] != Null) {
487  m_tableWin->table()->item(row + i, DistanceKmIndex)->setText(QString::number(m_distanceSegments[i]));
488  m_tableWin->table()->item(row + i, DistanceMIndex)->setText(QString::number(m_distanceSegments[i] * 1000.0));
489  }
490  else {
491  m_tableWin->table()->item(row + i, DistanceKmIndex)->setText("N/A");
492  m_tableWin->table()->item(row + i, DistanceMIndex)->setText("N/A");
493  }
494 
495  m_tableWin->table()->item(row + i, PathIndex)->setText(m_path);
496  m_tableWin->table()->item(row + i, FileNameIndex)->setText(m_fname);
497 
498  distanceSum = (Distance(distanceSum, Distance::Kilometers) +
499  Distance(m_distanceSegments[i], Distance::Kilometers)).kilometers();
500 
501  if (distanceSum != Null) {
502  m_tableWin->table()->item(row + i, SegmentsSumIndex)->setText(QString::number(distanceSum));
503  }
504  else {
505  m_tableWin->table()->item(row + i, SegmentsSumIndex)->setText("N/A");
506  }
507 
508  m_tableWin->table()->item(row + i, SegmentNumberIndex)->setText(QString::number(i + 1));
509  }
510  }
511  }
512 
519  // Initialize the class data
520  m_startSamp = Null;
521  m_endSamp = Null;
522  m_startLine = Null;
523  m_endLine = Null;
524  m_kmDist = Null;
525  m_mDist = Null;
526  m_pixDist = Null;
527  m_startLon = Null;
528  m_startLat = Null;
529  m_endLon = Null;
530  m_endLat = Null;
531  m_radAngle = Null;
532  m_degAngle = Null;
533  m_pixArea = Null;
534  m_kmArea = Null;
535  m_mArea = Null;
536  }
537 
538 
539  void MeasureTool::addRow() {
540  int newRowPos = m_tableWin->table()->rowCount();
541  m_tableWin->table()->insertRow(newRowPos);
542  for (int c = 0; c < m_tableWin->table()->columnCount(); c++) {
543  QTableWidgetItem *item = new QTableWidgetItem("");
544  m_tableWin->table()->setItem(newRowPos, c, item);
545  }
546  m_tableWin->table()->scrollToItem(m_tableWin->table()->item(newRowPos, 0),
547  QAbstractItemView::PositionAtBottom);
548  }
549 
550 
561  // Initialize class data
562  initData();
563 
564  // Write out col 8 (the file name)
566  cvp->cube()->fileName()).expanded();
567  m_path = fname.path();
568  m_fname = fname.name();
569 
570  m_pixDist = Null;
571  m_mDist = Null;
572  m_kmDist = Null;
573 
574  // reset the distnace gui
575  m_distLineEdit->setText("");
576 
577  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
578  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
579  m_distanceSegments.clear();
580  m_pixDistSegments.clear();
581  m_startSampSegments.clear();
582  m_endSampSegments.clear();
583  m_startLineSegments.clear();
584  m_endLineSegments.clear();
585  m_startLatSegments.clear();
586  m_endLatSegments.clear();
587  m_startLonSegments.clear();
588  m_endLonSegments.clear();
589 
590  for (int startIndex = 0; startIndex < rubberBandTool()->vertices().size() - 1; startIndex++) {
591  QPoint start = rubberBandTool()->vertices()[startIndex];
592  QPoint end = rubberBandTool()->vertices()[startIndex + 1];
593 
594  setDistances(cvp, start, end);
595 
596  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
597  if (m_distanceSegments.size() < 75) {
598  m_distanceSegments.append(m_kmDist);
599  m_pixDistSegments.append(m_pixDist);
600  m_startSampSegments.append(m_startSamp);
601  m_endSampSegments.append(m_endSamp);
602  m_startLineSegments.append(m_startLine);
603  m_endLineSegments.append(m_endLine);
604  m_startLatSegments.append(m_startLat);
605  m_endLatSegments.append(m_endLat);
606  m_startLonSegments.append(m_startLon);
607  m_endLonSegments.append(m_endLon);
608  }
609  }
610  }
611 
612  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode &&
613  m_pixDistSegments.size()) {
614  m_pixDist = m_pixDistSegments[0];
615  m_kmDist = m_distanceSegments[0];
617 
618  for (int i = 1; i < m_pixDistSegments.size(); i++) {
620  Distance(m_pixDistSegments[i], Distance::Pixels)).pixels();
621 
622  Distance thisDistance(m_distanceSegments[i], Distance::Kilometers);
624  thisDistance).kilometers();
626  thisDistance).meters();
627  }
628  }
629  }
630  else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
631  m_radAngle = rubberBandTool()->angle().radians();
632  m_degAngle = rubberBandTool()->angle().degrees();
633  }
634  else {
635  geos::geom::Geometry *polygon = rubberBandTool()->geometry();
636  if (polygon != NULL) {
637  // pix area = screenpix^2 / scale^2
638  m_pixArea = polygon->getArea() / pow(cvp->scale(), 2);
639  geos::geom::Point *center = polygon->getCentroid();
640  double line, sample;
641  cvp->viewportToCube((int)center->getX(), (int)center->getY(), sample, line);
642 
643  if (cvp->camera() != NULL) {
644  cvp->camera()->SetImage(sample, line);
645  // pix^2 * (m/pix)^2 = m^2
646  m_mArea = m_pixArea * pow(cvp->camera()->PixelResolution(), 2);
647  // m^2 * (km/m)^2 = km^2
648  m_kmArea = m_mArea * pow(1 / 1000.0, 2);
649  }
650 
651  if (cvp->projection() != NULL) {
652  cvp->projection()->SetWorld(sample, line);
653  // pix^2 * (m/pix)^2 = m^2
654  m_mArea = m_pixArea * pow(cvp->projection()->Resolution(), 2);
655  // m^2 * (km/m)^2 = km^2
656  m_kmArea = m_mArea * pow(1 / 1000.0, 2);
657  }
658  }
659 
660  if (rubberBandTool()->currentMode() == RubberBandTool::RectangleMode) {
661  setDistances(cvp, rubberBandTool()->vertices()[0],
662  rubberBandTool()->vertices()[2]);
663  }
664  }
665 
666  updateDistEdit();
667 
668  if (m_showAllSegments->isChecked() &&
669  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
670  updateRows(row);
671  }
672  else {
673  updateRow(row);
674  }
675  }
676 
677 
678  void MeasureTool::setDistances(MdiCubeViewport *cvp, QPoint lineStart,
679  QPoint lineEnd) {
680  // Convert rubber band line to cube coordinates
681  cvp->viewportToCube(lineStart.x(), lineStart.y(), m_startSamp, m_startLine);
682  cvp->viewportToCube(lineEnd.x(), lineEnd.y(), m_endSamp, m_endLine);
683 
684  m_mDist = Null;
685  m_kmDist = Null;
686  double radius = Null;
687  TProjection *tproj = NULL;
688  RingPlaneProjection *rproj = NULL;
690 
691  // Get set for dealing with projection types
692  if (cvp->projection() != NULL) projType = cvp->projection()->projectionType();
693 
694  // Don't write anything if we are outside the cube
695  if ((m_startSamp >= 0.5) && (m_endSamp >= 0.5) &&
696  (m_startLine >= 0.5) && (m_endLine >= 0.5) &&
697  (m_startSamp <= cvp->cubeSamples() + 0.5) &&
698  (m_endSamp <= cvp->cubeSamples() + 0.5) &&
699  (m_startLine <= cvp->cubeLines() + 0.5) &&
700  (m_endLine <= cvp->cubeLines() + 0.5)) {
701  // Check if the image is projected (Projected Images also have camera
702  // except for mosaics)
703  if (cvp->projection() != NULL) {
704  if (cvp->projection()->SetWorld(m_startSamp, m_startLine)) {
705  // If our projection is sky, the lat & lons are switched
706  if (cvp->projection()->IsSky()) {
707  tproj = (TProjection *) cvp->projection();
708  m_startLat = tproj->UniversalLatitude();
709  m_startLon = tproj->UniversalLongitude();
710  }
711  else if (projType == Projection::Triaxial) {
712  tproj = (TProjection *) cvp->projection();
713  m_startLat = tproj->UniversalLatitude();
714  m_startLon = tproj->UniversalLongitude();
715  }
716  else { // RingPlaneProjection
717  rproj = (RingPlaneProjection *) cvp->projection();
718  m_startLat = rproj->UniversalRingRadius();
720  }
721 
722  if (cvp->projection()->SetWorld(m_endSamp, m_endLine)) {
723  // If our projection is sky, the lat & lons are switched
724  if (cvp->projection()->IsSky()) {
725  m_endLat = tproj->UniversalLatitude();
726  m_endLon = tproj->UniversalLongitude();
727  }
728  else if (projType == Projection::Triaxial) {
729  m_endLat = tproj->UniversalLatitude();
730  m_endLon = tproj->UniversalLongitude();
731  } // RingPlaneProjection
732  else {
733  m_endLat = rproj->UniversalRingRadius();
734  m_endLon = rproj->UniversalRingLongitude();
735  }
736  }
737 
738  // Calculate and write out the distance between the two points
739  if (projType != Projection::RingPlane) {
740  radius = tproj->LocalRadius();
741  }
742  else {
743  radius = rproj->RingRadius();
744  }
745  }
746  }
747  // Do we have a camera model?
748  else if (cvp->camera() != NULL &&
750  // Write columns 2-3 (Start lat/lon)
751  m_startLat = cvp->camera()->UniversalLatitude();
753 
754  if (cvp->camera()->SetImage(m_endSamp, m_endLine)) {
755  // Write columns 4-5 (End lat/lon)
756  m_endLat = cvp->camera()->UniversalLatitude();
757  m_endLon = cvp->camera()->UniversalLongitude();
758 
759  radius = cvp->camera()->LocalRadius().meters();
760  }
761  }
762  }
763 
764  // Calculate the pixel difference
765  double lineDif = m_startLine - m_endLine;
766  double sampDif = m_startSamp - m_endSamp;
767  double pixDist = sqrt(lineDif * lineDif + sampDif * sampDif);
768  m_pixDist = pixDist;
769 
770  Latitude startLat(m_startLat, Angle::Degrees);
771  Longitude startLon(m_startLon, Angle::Degrees);
772  Latitude endLat(m_endLat, Angle::Degrees);
773  Longitude endLon(m_endLon, Angle::Degrees);
774  Distance radiusDist(radius, Distance::Meters);
775 
776  SurfacePoint startPoint;
777  SurfacePoint endPoint;
778 
779  if (startLat.isValid() && startLon.isValid() &&
780  endLat.isValid() && endLon.isValid() && radiusDist.isValid()) {
781  startPoint = SurfacePoint(startLat, startLon, radiusDist);
782  endPoint = SurfacePoint(endLat, endLon, radiusDist);
783  }
784 
785  Distance distance = startPoint.GetDistanceToPoint(endPoint, radiusDist);
786 
787  m_mDist = distance.meters();
788  m_kmDist = distance.kilometers();
789  }
790 
791 
794  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
795  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
796  if (m_unitsComboBox->currentIndex() == 0) {
797  if (m_kmDist == Null) {
798  m_distLineEdit->setText("N/A");
799  }
800  else {
801  m_distLineEdit->setText(QString::number(m_kmDist));
802  }
803  }
804  else if (m_unitsComboBox->currentIndex() == 1) {
805  if (m_mDist == Null) {
806  m_distLineEdit->setText("N/A");
807  }
808  else {
809  m_distLineEdit->setText(QString::number(m_mDist));
810  }
811  }
812  else {
813  m_distLineEdit->setText(QString::number(m_pixDist));
814  }
815  }
816  else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
817  if (m_unitsComboBox->currentIndex() == 0) {
818  m_distLineEdit->setText(QString::number(m_degAngle));
819  }
820  else {
821  m_distLineEdit->setText(QString::number(m_radAngle));
822  }
823  }
824  else {
825  if (m_unitsComboBox->currentIndex() == 0) {
826  if (m_kmArea == Null) {
827  m_distLineEdit->setText("N/A");
828  }
829  else {
830  m_distLineEdit->setText(QString::number(m_kmArea));
831  }
832  }
833  else if (m_unitsComboBox->currentIndex() == 1) {
834  if (m_mArea == Null) {
835  m_distLineEdit->setText("N/A");
836  }
837  else {
838  m_distLineEdit->setText(QString::number(m_mArea));
839  }
840  }
841  else {
842  if (m_pixArea != Null) {
843  m_distLineEdit->setText(QString::number(m_pixArea));
844  }
845  else {
846  m_distLineEdit->setText("N/A");
847  }
848  }
849  }
850  }
851 
852 
860  // cvp->repaint();
861  cvp->update();
862  }
863 
864 
870  m_distLineEdit->clear();
871  }
872 
873 }
874 
Cube display widget for certain Isis MDI applications.
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition: Tool.cpp:390
void updateRow(int row)
This method updates the row in the table window with the current measure information.
void reset()
Resets the selection.
double m_startLine
starting line
Definition: MeasureTool.h:150
QTableWidget * table() const
Returns the table.
virtual void mouseLeave()
Mouse leave event.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:109
void setStatusMessage(QString message)
sets the status message in the lower lefthand corner of the window.
Angle in radians index.
Definition: MeasureTool.h:138
bool IsSky() const
Returns true if projection is sky and false if it is land.
Definition: Projection.cpp:223
double m_pixDist
distance in pixels
Definition: MeasureTool.h:158
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:245
File name manipulation and expansion.
Definition: FileName.h:111
double m_endSamp
ending sample
Definition: MeasureTool.h:149
QLineEdit * m_distLineEdit
Distance line edit.
Definition: MeasureTool.h:89
double radians() const
Convert an angle to a double.
Definition: Angle.h:239
double m_startLat
starting latitude
Definition: MeasureTool.h:152
QList< QPoint > vertices()
This method returns the vertices.
Base class for Map TProjections.
Definition: TProjection.h:178
void clearRow(int row)
This method clears the text of the given row.
double m_startLon
starting longitude
Definition: MeasureTool.h:154
int m_numLinked
number of linked viewports
Definition: MeasureTool.h:177
Combo box for choosing a rubber band type.
Distance in meters index.
Definition: MeasureTool.h:135
double m_degAngle
angle in degrees
Definition: MeasureTool.h:160
void initData(void)
Initialize Class data.
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
QAction * m_action
Measure tool&#39;s action.
Definition: MeasureTool.h:88
double m_kmArea
area in kilometers
Definition: MeasureTool.h:161
double m_endLon
ending longitude
Definition: MeasureTool.h:155
void enableRubberBandTool()
Enables/resets the rubberband tool.
double LocalRadius(double lat) const
This method returns the local radius in meters at the specified latitude position.
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
void setDrawActiveViewportOnly(bool activeOnly=false)
This called to set whether rubber band is drawn on active viewport only rather than all linked viewpo...
The distance is being specified in kilometers.
Definition: Distance.h:58
int currentRow() const
Returns the current row.
Segment lengths in kilometers.
Definition: MeasureTool.h:142
Projection * projection() const
Return the projection associated with cube (NULL implies none)
Definition: CubeViewport.h:233
QString m_path
filename path
Definition: MeasureTool.h:178
Ending latitude index.
Definition: MeasureTool.h:128
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Distance measurement, usually in meters.
Definition: Distance.h:47
virtual void rubberBandComplete()
Called when the rubberBanding by the user is finished.
MeasureTool(QWidget *parent)
MeasureTool constructor.
Definition: MeasureTool.cpp:39
void addTo(QMenu *menu)
Adds the measure action to the given menu.
void updateDistEdit()
Change the value in the distance edit to match the units.
Distance in pixels index.
Definition: MeasureTool.h:136
Angle in degrees index.
Definition: MeasureTool.h:137
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
void setTrackListItems(bool track=false)
If this property is true, the class will keep track of the checked/unchecked items in the dock area w...
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:166
QWidget * createToolBarWidget(QStackedWidget *parent)
Creates the widget (button) that goes on the tool bar.
These projections are used to map ring planes.
Definition: Projection.h:182
double meters() const
Get the distance in meters.
Definition: Distance.cpp:97
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:211
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:69
Cube * cube() const
Return the cube associated with viewport.
Definition: CubeViewport.h:228
RubberBandComboBox * m_rubberBand
rubberband combo box
Definition: MeasureTool.h:182
double m_startSamp
starting sample
Definition: MeasureTool.h:148
void updateTool()
Updates the measure tool.
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
Definition: Projection.cpp:661
Ending sample index.
Definition: MeasureTool.h:132
Camera * camera() const
Return the camera associated with the cube (NULL implies none)
Definition: CubeViewport.h:238
double UniversalRingRadius()
This returns a universal radius, which is just the radius in meters.
QAction * toolPadAction(ToolPad *pad)
Add the measure tool action to the toolpad.
Definition: MeasureTool.cpp:88
double m_endLat
ending latitude
Definition: MeasureTool.h:153
bool isLinked() const
Is the viewport linked with other viewports.
void updateUnitsCombo()
Updates the units combo box.
QString m_fname
filename
Definition: MeasureTool.h:179
TableMainWindow * m_tableWin
table window
Definition: MeasureTool.h:181
void viewportToCube(int x, int y, double &sample, double &line) const
Convert a viewport x/y to a cube sample/line (may be outside the cube)
double m_endLine
ending line
Definition: MeasureTool.h:151
double m_kmDist
distance in kilometers
Definition: MeasureTool.h:156
Starting sample index.
Definition: MeasureTool.h:130
void updateDist(MdiCubeViewport *cvp, int row)
This method updates the distance variables.
FileName path index.
Definition: MeasureTool.h:144
void setCurrentRow(int row)
Sets the current row to row.
double UniversalLatitude()
This returns a universal latitude (planetocentric).
double m_pixArea
area in pixels
Definition: MeasureTool.h:163
Area in pixels index.
Definition: MeasureTool.h:141
a subclass of the qisis mainwindow, tablemainwindow handles all of the table tasks.
Area in meters index.
Definition: MeasureTool.h:140
Starting longitude index.
Definition: MeasureTool.h:127
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:483
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition: Sensor.cpp:282
Base class for Map Projections of plane shapes.
Area in kilometers index.
Definition: MeasureTool.h:139
Distance in kilometers index.
Definition: MeasureTool.h:134
double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
Definition: Camera.cpp:744
QComboBox * m_unitsComboBox
Units selection.
Definition: MeasureTool.h:90
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:127
double RingRadius() const
This returns a radius.
Base class for the Qisis tools.
Definition: Tool.h:81
geos::geom::Geometry * geometry()
QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1160
The distance is being specified in meters.
Definition: Distance.h:56
double scale() const
Return the scale.
Definition: CubeViewport.h:183
void addToTable(bool setOn, const QString &heading, const QString &menuText="", int insertAt=-1, Qt::Orientation o=Qt::Horizontal, QString toolTip="")
Adds a new column to the table when a new curve is added to the plot.
void removeConnections(MdiCubeViewport *cvp)
Removes the connection on the given cube viewport.
ProjectionType projectionType() const
Returns an enum value for the projection type.
Definition: Projection.cpp:213
void updateRows(int row)
This method is called instead of updateRows if the &#39;Show All Segment&#39; checkbox is checked...
QString path() const
Returns the path.
Definition: FileName.cpp:88
The distance is being specified in pixels.
Definition: Distance.h:60
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition: Projection.h:180
double m_mDist
distance in meters
Definition: MeasureTool.h:157
double m_radAngle
angle in radians
Definition: MeasureTool.h:159
double UniversalRingLongitude()
This returns a universal ring longitude (clockwise in 0 to 360 domain).
Ending longitude index.
Definition: MeasureTool.h:129
double m_mArea
area in meters
Definition: MeasureTool.h:162
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Starting latitude index.
Definition: MeasureTool.h:126
These projections are used to map triaxial and irregular-shaped bodies.
Definition: Projection.h:180
virtual void updateMeasure()
Updates the Measure specifications.

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:23:23