Isis 3 Programmer Reference
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.
void updateRow(int row)
This method updates the row in the table window with the current measure information.
void reset()
Resets the selection.
QString path() const
Returns the path of the file name.
Definition: FileName.cpp:119
double meters() const
Get the distance in meters.
Definition: Distance.cpp:97
double m_startLine
starting line
Definition: MeasureTool.h:150
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:127
virtual void mouseLeave()
Mouse leave event.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
void setStatusMessage(QString message)
sets the status message in the lower lefthand corner of the window.
Angle in radians index.
Definition: MeasureTool.h:138
Cube * cube() const
Definition: CubeViewport.h:348
double m_pixDist
distance in pixels
Definition: MeasureTool.h:158
File name manipulation and expansion.
Definition: FileName.h:116
ProjectionType projectionType() const
Returns an enum value for the projection type.
Definition: Projection.cpp:213
double m_endSamp
ending sample
Definition: MeasureTool.h:149
QLineEdit * m_distLineEdit
Distance line edit.
Definition: MeasureTool.h:89
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
double m_startLat
starting latitude
Definition: MeasureTool.h:152
QList< QPoint > vertices()
This method returns the vertices.
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition: Tool.cpp:390
double radians() const
Convert an angle to a double.
Definition: Angle.h:243
Base class for Map TProjections.
Definition: TProjection.h:182
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.
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.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
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
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
Definition: Projection.cpp:690
Segment lengths in kilometers.
Definition: MeasureTool.h:142
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.
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
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
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition: Sensor.cpp:282
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:170
QWidget * createToolBarWidget(QStackedWidget *parent)
Creates the widget (button) that goes on the tool bar.
Camera * camera() const
Definition: CubeViewport.h:358
These projections are used to map ring planes.
Definition: Projection.h:184
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
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.
Ending sample index.
Definition: MeasureTool.h:132
int currentRow() const
Returns the current row.
bool IsSky() const
Returns true if projection is sky and false if it is land.
Definition: Projection.cpp:223
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 LocalRadius(double lat) const
This method returns the local radius in meters at the specified latitude position.
double m_endLat
ending latitude
Definition: MeasureTool.h:153
void updateUnitsCombo()
Updates the units combo box.
bool isLinked() const
Is the viewport linked with other viewports.
QString m_fname
filename
Definition: MeasureTool.h:179
TableMainWindow * m_tableWin
table window
Definition: MeasureTool.h:181
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
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 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.
double RingRadius() const
This returns a radius.
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:512
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
QTableWidget * table() const
Returns the table.
Base class for Map Projections of plane shapes.
Area in kilometers index.
Definition: MeasureTool.h:139
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
Distance in kilometers index.
Definition: MeasureTool.h:134
double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
Definition: Camera.cpp:689
QComboBox * m_unitsComboBox
Units selection.
Definition: MeasureTool.h:90
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Projection * projection() const
Definition: CubeViewport.h:353
Base class for the Qisis tools.
Definition: Tool.h:81
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:211
geos::geom::Geometry * geometry()
The distance is being specified in meters.
Definition: Distance.h:56
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.
void updateRows(int row)
This method is called instead of updateRows if the &#39;Show All Segment&#39; checkbox is checked...
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
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:182
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
double scale() const
Definition: CubeViewport.h:224
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:182
virtual void updateMeasure()
Updates the Measure specifications.