USGS

Isis 3.0 Object Programmers' Reference

Home

MeasureTool.cpp
1 #include "IsisDebug.h"
2 #include "MeasureTool.h"
3 
4 #include <QApplication>
5 #include <QFileDialog>
6 #include <QHBoxLayout>
7 #include <QLineEdit>
8 #include <QMenu>
9 #include <QMenuBar>
10 #include <QMessageBox>
11 #include <QStatusBar>
12 
13 #include <geos/geom/Geometry.h>
14 #include <geos/geom/Point.h>
15 
16 #include "Camera.h"
17 #include "Distance.h"
18 #include "FileName.h"
19 #include "Latitude.h"
20 #include "Longitude.h"
21 #include "MdiCubeViewport.h"
22 #include "Projection.h"
23 #include "RingPlaneProjection.h"
24 #include "TProjection.h"
25 #include "SurfacePoint.h"
26 #include "ToolPad.h"
27 
28 namespace Isis {
35  MeasureTool::MeasureTool(QWidget *parent) : Tool(parent) {
36  m_rubberBand = NULL;
37  m_tableWin = new TableMainWindow("Measurements", parent);
39 
40  // Create the action for showing the table
41  m_action = new QAction(parent);
42  m_action->setText("Measuring ...");
43 
44  connect(m_action, SIGNAL(triggered()), m_tableWin, SLOT(showTable()));
45  connect(m_action, SIGNAL(triggered()), m_tableWin, SLOT(raise()));
46  connect(m_action, SIGNAL(triggered()), m_tableWin, SLOT(syncColumns()));
47  //m_tableWin->installEventFilter(this);
48 
49  m_tableWin->addToTable(false, "Feature\nName", "Feature Name");
50  m_tableWin->addToTable(false, "Feature\nType", "Feature Type");
51  m_tableWin->addToTable(true,
52  "Start\nLatitude:Start\nLongitude:End\nLatitude:End\nLongitude",
53  "Ground Range", -1, Qt::Horizontal, "Start Latitude/Longitude to End Latitude/Longitude");
54  m_tableWin->addToTable(false, "Start\nSample:Start\nLine:End\nSample:End\nLine",
55  "Pixel Range", -1, Qt::Horizontal, "Start Sample/Line to End Sample/Line");
56  m_tableWin->addToTable(true, "Kilometer\nDistance", "Kilometer Distance");
57  m_tableWin->addToTable(false, "Meter\nDistance", "Meter Distance");
58  m_tableWin->addToTable(false, "Pixel\nDistance", "Pixel Distance");
59  m_tableWin->addToTable(false, "Degree\nAngle", "Degree Angle");
60  m_tableWin->addToTable(false, "Radian\nAngle", "Radian Angle");
61  m_tableWin->addToTable(false, "Kilometer\nArea", "Kilometer Area");
62  m_tableWin->addToTable(false, "Meter\nArea", "Meter Area");
63  m_tableWin->addToTable(false, "Pixel\nArea", "Pixel Area");
64  m_tableWin->addToTable(false, "Segments Sum\nkm", "Segments Sum", -1, Qt::Horizontal, "Sum of Segment lengths in kilometers");
65  m_tableWin->addToTable(false, "Segment Number", "Segment Number", -1, Qt::Horizontal, "Segment number of a segmented line");
66  m_tableWin->addToTable(false, "Path", "Path");
67  m_tableWin->addToTable(false, "FileName", "FileName");
68  m_tableWin->addToTable(false, "Notes", "Notes");
69 
70  m_tableWin->setStatusMessage("Click, Drag, and Release to Measure a Line");
71 
72  addRow();
73  }
74 
75 
85  QAction *action = new QAction(toolpad);
86  action->setIcon(QPixmap(toolIconDir() + "/measure.png"));
87  action->setToolTip("Measure (M)");
88  action->setShortcut(Qt::Key_M);
89 
90  QString text =
91  "<b>Function:</b> Measure features in active viewport \
92  <p><b>Shortcut:</b> M</p> ";
93  action->setWhatsThis(text);
94 
95  return action;
96  }
97 
98 
107  QWidget *MeasureTool::createToolBarWidget(QStackedWidget *parent) {
108  QWidget *hbox = new QWidget(parent);
109  QToolButton *measureButton = new QToolButton(hbox);
110  measureButton->setText("Table");
111  measureButton->setToolTip("Record Measurement Data in Table");
112  QString text =
113  "<b>Function:</b> This button will bring up a table that will record the \
114  starting and ending points of the line, along with the distance between \
115  the two points on the image. To measure the distance between two points, \
116  click on the first point and releasing the mouse at the second point. \
117  <p><b>Shortcut:</b> CTRL+M</p>";
118  measureButton->setWhatsThis(text);
119  measureButton->setShortcut(Qt::CTRL + Qt::Key_M);
120  connect(measureButton, SIGNAL(clicked()), m_tableWin, SLOT(showTable()));
121  connect(measureButton, SIGNAL(clicked()), m_tableWin, SLOT(syncColumns()));
122  connect(measureButton, SIGNAL(clicked()), m_tableWin, SLOT(raise()));
123  measureButton->setEnabled(true);
124 
125  m_rubberBand = new RubberBandComboBox(this,
134  RubberBandComboBox::Line // default
135  );
136 
137  m_distLineEdit = new QLineEdit(hbox);
138  m_distLineEdit->setText("");
139  m_distLineEdit->setMaxLength(12);
140  m_distLineEdit->setToolTip("Line Length");
141  QString text2 = "<b>Function: </b> Shows the length of the line drawn on \
142  the image.";
143  m_distLineEdit->setWhatsThis(text2);
144  m_distLineEdit->setReadOnly(true);
145 
146  m_showAllSegments = new QCheckBox(hbox);
147  m_showAllSegments->setText("Show All Segments");
148 
149  m_unitsComboBox = new QComboBox(hbox);
150  m_unitsComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
151 
152  miComboUnit = -1;
153 
155  connect(m_unitsComboBox, SIGNAL(activated(int)), this, SLOT(updateDistEdit()));
156  connect(rubberBandTool(), SIGNAL(modeChanged()), this, SLOT(updateUnitsCombo()));
157 
158  QHBoxLayout *layout = new QHBoxLayout(hbox);
159  layout->setMargin(0);
160  layout->addWidget(m_rubberBand);
161  layout->addWidget(m_distLineEdit);
162  layout->addWidget(m_unitsComboBox);
163  layout->addWidget(measureButton);
164  layout->addWidget(m_showAllSegments);
165  layout->addStretch(1);
166  hbox->setLayout(layout);
167  return hbox;
168  }
169 
170 
176  // get the previous index if not initializing
177  if (miComboUnit >= 0) {
178  miComboUnit = m_unitsComboBox->currentIndex();
179  }
180 
181  m_unitsComboBox->clear();
182  m_showAllSegments->setEnabled(false);
183 
184  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
185  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
186 
187  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
188  m_showAllSegments->setEnabled(true);
189  }
190 
191  m_unitsComboBox->addItem("km");
192  m_unitsComboBox->addItem("m");
193  m_unitsComboBox->addItem("pixels");
194  if (miComboUnit < 0 || miComboUnit > 2) { // default && error checking
195  miComboUnit = 2;
196  }
197  }
198  else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
199  m_unitsComboBox->addItem("degrees");
200  m_unitsComboBox->addItem("radians");
201  if (miComboUnit > 1 || miComboUnit < 0) { // default && error checking
202  miComboUnit = 0;
203  }
204  }
205  else {
206  m_unitsComboBox->addItem("km^2");
207  m_unitsComboBox->addItem("m^2");
208  m_unitsComboBox->addItem("pix^2");
209  if (miComboUnit < 0 || miComboUnit > 2) { // default && error checking
210  miComboUnit = 2;
211  }
212  }
213 
214  m_unitsComboBox->setCurrentIndex(miComboUnit);
215  }
216 
217 
224  void MeasureTool::addTo(QMenu *menu) {
225  menu->addAction(m_action);
226  }
227 
228 
234  MdiCubeViewport *cvp = cubeViewport();
235  MdiCubeViewport *d;
236  m_numLinked = 0;
237 
238  int currentRow = m_tableWin->currentRow();
239 
240  while (currentRow >= m_tableWin->table()->rowCount()) {
241  addRow();
242  }
243 
244  if (cvp == NULL) {
246  }
247  else {
248  updateDist(cvp, currentRow);
249  m_tableWin->table()->selectRow(currentRow);
250 
251  if (cvp->isLinked()) {
252  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
253  d = (*(cubeViewportList()))[i];
254 
255  if (d->isLinked() && d != cvp) {
256  m_numLinked++;
257 
258  if (currentRow + m_numLinked >= m_tableWin->table()->rowCount()) {
259  addRow();
260  }
261 
262  updateDist(d, currentRow + m_numLinked);
263  }
264  }
265  }
266  }
267  }
268 
269 
275  updateMeasure();
276 
277  if (rubberBandTool()->currentMode() != RubberBandTool::AngleMode && m_unitsComboBox->currentIndex() != 2) {
278  if (cubeViewport()->camera() == NULL && cubeViewport()->projection() == NULL) {
279  QMessageBox::information((QWidget *)parent(), "Error",
280  "File must have a Camera Model or Projection to measure in km or m");
281  return;
282  }
283  }
284 
285  if (!m_tableWin->table()->isVisible()) return;
286  if (m_tableWin->table()->item(m_tableWin->currentRow(), StartLineIndex)->text() == "N/A" &&
287  m_tableWin->table()->item(m_tableWin->currentRow(), AngleDegIndex)->text() == "N/A" &&
288  m_tableWin->table()->item(m_tableWin->currentRow(), AreaPixIndex)->text() == "N/A") return;
289 
290  addRow();
291  m_tableWin->setCurrentRow(m_tableWin->table()->rowCount() - 1);
292 
293  QApplication::sendPostedEvents(m_tableWin->table(), 0);
294  }
295 
296 
302  //m_tableWin->clearRow(m_tableWin->currentRow());
303  }
304 
305 
311  if (m_rubberBand) {
312  m_rubberBand->reset();
313  rubberBandTool()->setDrawActiveViewportOnly(false);
314  }
315  }
316 
317 
325  void MeasureTool::updateRow(int row) {
326  ASSERT(row < m_tableWin->table()->rowCount());
327 
328  if (row >= m_tableWin->table()->rowCount()) {
329  return;
330  }
331 
332  // Blank out the row to remove stuff left over from previous cvps
333  for (int c = 0; c < m_tableWin->table()->columnCount(); c++) {
334  m_tableWin->table()->item(row, c)->setText("");
335  }
336 
337  // Write all the new info to the current row
338  if (m_startLat != Null && m_startLon != Null) {
339  m_tableWin->table()->item(row, StartLatIndex)->setText(QString::number(m_startLat));
340  m_tableWin->table()->item(row, StartLonIndex)->setText(QString::number(m_startLon));
341  }
342  else {
343  m_tableWin->table()->item(row, StartLatIndex)->setText("N/A");
344  m_tableWin->table()->item(row, StartLonIndex)->setText("N/A");
345  }
346 
347  if (m_endLat != Null && m_endLon != Null) {
348  m_tableWin->table()->item(row, EndLatIndex)->setText(QString::number(m_endLat));
349  m_tableWin->table()->item(row, EndLonIndex)->setText(QString::number(m_endLon));
350  }
351  else {
352  m_tableWin->table()->item(row, EndLatIndex)->setText("N/A");
353  m_tableWin->table()->item(row, EndLonIndex)->setText("N/A");
354  }
355 
356  if (m_mDist != Null && m_kmDist != Null) {
357  m_tableWin->table()->item(row, DistanceMIndex)->setText(QString::number(m_mDist));
358  m_tableWin->table()->item(row, DistanceKmIndex)->setText(QString::number(m_kmDist));
359  }
360  else {
361  m_tableWin->table()->item(row, DistanceKmIndex)->setText("N/A");
362  m_tableWin->table()->item(row, DistanceMIndex)->setText("N/A");
363  }
364 
365  if (m_degAngle != Null && m_radAngle != Null) {
366  m_tableWin->table()->item(row, AngleDegIndex)->setText(QString::number(m_degAngle));
367  m_tableWin->table()->item(row, AngleRadIndex)->setText(QString::number(m_radAngle));
368  }
369  else {
370  m_tableWin->table()->item(row, AngleDegIndex)->setText("N/A");
371  m_tableWin->table()->item(row, AngleRadIndex)->setText("N/A");
372  }
373 
374  if (m_startSamp != Null && m_startLine != Null) {
375  m_tableWin->table()->item(row, StartSampIndex)->setText(QString::number(m_startSamp));
376  m_tableWin->table()->item(row, StartLineIndex)->setText(QString::number(m_startLine));
377  }
378  else {
379  m_tableWin->table()->item(row, StartSampIndex)->setText("N/A");
380  m_tableWin->table()->item(row, StartLineIndex)->setText("N/A");
381  }
382 
383  if (m_endSamp != Null && m_endLine != Null) {
384  m_tableWin->table()->item(row, EndSampIndex)->setText(QString::number(m_endSamp));
385  m_tableWin->table()->item(row, EndLineIndex)->setText(QString::number(m_endLine));
386  m_tableWin->table()->item(row, DistancePixIndex)->setText(QString::number(m_pixDist));
387  }
388  else {
389  m_tableWin->table()->item(row, EndSampIndex)->setText("N/A");
390  m_tableWin->table()->item(row, EndLineIndex)->setText("N/A");
391  m_tableWin->table()->item(row, DistancePixIndex)->setText("N/A");
392  }
393 
394  if (m_pixArea != Null) {
395  m_tableWin->table()->item(row, AreaPixIndex)->setText(QString::number(m_pixArea));
396  }
397  else {
398  m_tableWin->table()->item(row, AreaPixIndex)->setText("N/A");
399  }
400 
401  if (m_mArea != Null) {
402  m_tableWin->table()->item(row, AreaKmIndex)->setText(QString::number(m_kmArea));
403  m_tableWin->table()->item(row, AreaMIndex)->setText(QString::number(m_mArea));
404  }
405  else {
406  m_tableWin->table()->item(row, AreaKmIndex)->setText("N/A");
407  m_tableWin->table()->item(row, AreaMIndex)->setText("N/A");
408  }
409 
410  m_tableWin->table()->item(row, PathIndex)->setText(m_path);
411  m_tableWin->table()->item(row, FileNameIndex)->setText(m_fname);
412  }
413 
414 
415 
423  void MeasureTool::updateRows(int row) {
424  int requiredRows = m_distanceSegments.size() + row;
425  int rowDiff = (int)(requiredRows - m_tableWin->table()->rowCount());
426 
427  //Make sure we have all the necessary rows and items in each table cell.
428  if (requiredRows > m_tableWin->table()->rowCount()) {
429  for (int r = 0; r < rowDiff; r++) {
430  addRow();
431  }
432  }
433 
434  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode &&
435  m_distanceSegments.size() > 0) {
436  double distanceSum = 0;
437  for (int i = 0; i < m_distanceSegments.size(); i++) {
438  //write a new row for each segment...
439  if (m_startLatSegments[i] != Null && m_startLonSegments[i] != Null) {
440  m_tableWin->table()->item(row + i, StartLatIndex)->setText(QString::number(m_startLatSegments[i]));
441  m_tableWin->table()->item(row + i, StartLonIndex)->setText(QString::number(m_startLonSegments[i]));
442  }
443  else {
444  m_tableWin->table()->item(row + i, StartLatIndex)->setText("N/A");
445  m_tableWin->table()->item(row + i, StartLonIndex)->setText("N/A");
446  }
447 
448  if (m_endLatSegments[i] != Null && m_endLonSegments[i] != Null) {
449  m_tableWin->table()->item(row + i, EndLatIndex)->setText(QString::number(m_endLatSegments[i]));
450  m_tableWin->table()->item(row + i, EndLonIndex)->setText(QString::number(m_endLonSegments[i]));
451  }
452  else {
453  m_tableWin->table()->item(row + i, EndLatIndex)->setText("N/A");
454  m_tableWin->table()->item(row + i, EndLonIndex)->setText("N/A");
455  }
456 
457  if (m_startSampSegments[i] != Null && m_startLineSegments[i] != Null) {
458  m_tableWin->table()->item(row + i, StartSampIndex)->setText(QString::number(m_startSampSegments[i]));
459  m_tableWin->table()->item(row + i, StartLineIndex)->setText(QString::number(m_startLineSegments[i]));
460  }
461  else {
462  m_tableWin->table()->item(row + i, StartSampIndex)->setText("N/A");
463  m_tableWin->table()->item(row + i, StartLineIndex)->setText("N/A");
464  }
465 
466  if (m_endSampSegments[i] != Null && m_endLineSegments[i] != Null) {
467  m_tableWin->table()->item(row + i, EndSampIndex)->setText(QString::number(m_endSampSegments[i]));
468  m_tableWin->table()->item(row + i, EndLineIndex)->setText(QString::number(m_endLineSegments[i]));
469  }
470  else {
471  m_tableWin->table()->item(row + i, EndSampIndex)->setText("N/A");
472  m_tableWin->table()->item(row + i, EndLineIndex)->setText("N/A");
473  }
474 
475  if (m_pixDistSegments[i] != Null) {
476  m_tableWin->table()->item(row + i, DistancePixIndex)->setText(QString::number(m_pixDistSegments[i]));
477  }
478  else {
479  m_tableWin->table()->item(row + i, DistancePixIndex)->setText("N/A");
480  }
481 
482  if (m_distanceSegments[i] != Null) {
483  m_tableWin->table()->item(row + i, DistanceKmIndex)->setText(QString::number(m_distanceSegments[i]));
484  m_tableWin->table()->item(row + i, DistanceMIndex)->setText(QString::number(m_distanceSegments[i] * 1000.0));
485  }
486  else {
487  m_tableWin->table()->item(row + i, DistanceKmIndex)->setText("N/A");
488  m_tableWin->table()->item(row + i, DistanceMIndex)->setText("N/A");
489  }
490 
491  m_tableWin->table()->item(row + i, PathIndex)->setText(m_path);
492  m_tableWin->table()->item(row + i, FileNameIndex)->setText(m_fname);
493 
494  distanceSum = (Distance(distanceSum, Distance::Kilometers) +
495  Distance(m_distanceSegments[i], Distance::Kilometers)).kilometers();
496 
497  if (distanceSum != Null) {
498  m_tableWin->table()->item(row + i, SegmentsSumIndex)->setText(QString::number(distanceSum));
499  }
500  else {
501  m_tableWin->table()->item(row + i, SegmentsSumIndex)->setText("N/A");
502  }
503 
504  m_tableWin->table()->item(row + i, SegmentNumberIndex)->setText(QString::number(i + 1));
505  }
506  }
507  }
508 
515  // Initialize the class data
516  m_startSamp = Null;
517  m_endSamp = Null;
518  m_startLine = Null;
519  m_endLine = Null;
520  m_kmDist = Null;
521  m_mDist = Null;
522  m_pixDist = Null;
523  m_startLon = Null;
524  m_startLat = Null;
525  m_endLon = Null;
526  m_endLat = Null;
527  m_radAngle = Null;
528  m_degAngle = Null;
529  m_pixArea = Null;
530  m_kmArea = Null;
531  m_mArea = Null;
532  }
533 
534 
535  void MeasureTool::addRow() {
536  int newRowPos = m_tableWin->table()->rowCount();
537  m_tableWin->table()->insertRow(newRowPos);
538  for (int c = 0; c < m_tableWin->table()->columnCount(); c++) {
539  QTableWidgetItem *item = new QTableWidgetItem("");
540  m_tableWin->table()->setItem(newRowPos, c, item);
541  }
542  m_tableWin->table()->scrollToItem(m_tableWin->table()->item(newRowPos, 0),
543  QAbstractItemView::PositionAtBottom);
544  }
545 
546 
557  // Initialize class data
558  initData();
559 
560  // Write out col 8 (the file name)
562  cvp->cube()->fileName()).expanded();
563  m_path = fname.path();
564  m_fname = fname.name();
565 
566  m_pixDist = Null;
567  m_mDist = Null;
568  m_kmDist = Null;
569 
570  // reset the distnace gui
571  m_distLineEdit->setText("");
572 
573  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
574  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
575  m_distanceSegments.clear();
576  m_pixDistSegments.clear();
577  m_startSampSegments.clear();
578  m_endSampSegments.clear();
579  m_startLineSegments.clear();
580  m_endLineSegments.clear();
581  m_startLatSegments.clear();
582  m_endLatSegments.clear();
583  m_startLonSegments.clear();
584  m_endLonSegments.clear();
585 
586  for (int startIndex = 0; startIndex < rubberBandTool()->vertices().size() - 1; startIndex++) {
587  QPoint start = rubberBandTool()->vertices()[startIndex];
588  QPoint end = rubberBandTool()->vertices()[startIndex + 1];
589 
590  setDistances(cvp, start, end);
591 
592  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
593  if (m_distanceSegments.size() < 75) {
594  m_distanceSegments.append(m_kmDist);
595  m_pixDistSegments.append(m_pixDist);
596  m_startSampSegments.append(m_startSamp);
597  m_endSampSegments.append(m_endSamp);
598  m_startLineSegments.append(m_startLine);
599  m_endLineSegments.append(m_endLine);
600  m_startLatSegments.append(m_startLat);
601  m_endLatSegments.append(m_endLat);
602  m_startLonSegments.append(m_startLon);
603  m_endLonSegments.append(m_endLon);
604  }
605  }
606  }
607 
608  if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode &&
609  m_pixDistSegments.size()) {
610  m_pixDist = m_pixDistSegments[0];
611  m_kmDist = m_distanceSegments[0];
613 
614  for (int i = 1; i < m_pixDistSegments.size(); i++) {
616  Distance(m_pixDistSegments[i], Distance::Pixels)).pixels();
617 
618  Distance thisDistance(m_distanceSegments[i], Distance::Kilometers);
620  thisDistance).kilometers();
622  thisDistance).meters();
623  }
624  }
625  }
626  else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
627  m_radAngle = rubberBandTool()->angle().radians();
628  m_degAngle = rubberBandTool()->angle().degrees();
629  }
630  else {
631  geos::geom::Geometry *polygon = rubberBandTool()->geometry();
632  if (polygon != NULL) {
633  // pix area = screenpix^2 / scale^2
634  m_pixArea = polygon->getArea() / pow(cvp->scale(), 2);
635  geos::geom::Point *center = polygon->getCentroid();
636  double line, sample;
637  cvp->viewportToCube((int)center->getX(), (int)center->getY(), sample, line);
638 
639  if (cvp->camera() != NULL) {
640  cvp->camera()->SetImage(sample, line);
641  // pix^2 * (m/pix)^2 = m^2
642  m_mArea = m_pixArea * pow(cvp->camera()->PixelResolution(), 2);
643  // m^2 * (km/m)^2 = km^2
644  m_kmArea = m_mArea * pow(1 / 1000.0, 2);
645  }
646 
647  if (cvp->projection() != NULL) {
648  cvp->projection()->SetWorld(sample, line);
649  // pix^2 * (m/pix)^2 = m^2
650  m_mArea = m_pixArea * pow(cvp->projection()->Resolution(), 2);
651  // m^2 * (km/m)^2 = km^2
652  m_kmArea = m_mArea * pow(1 / 1000.0, 2);
653  }
654  }
655 
656  if (rubberBandTool()->currentMode() == RubberBandTool::RectangleMode) {
657  setDistances(cvp, rubberBandTool()->vertices()[0],
658  rubberBandTool()->vertices()[2]);
659  }
660  }
661 
662  updateDistEdit();
663 
664  if (m_showAllSegments->isChecked() &&
665  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
666  updateRows(row);
667  }
668  else {
669  updateRow(row);
670  }
671  }
672 
673 
674  void MeasureTool::setDistances(MdiCubeViewport *cvp, QPoint lineStart,
675  QPoint lineEnd) {
676  // Convert rubber band line to cube coordinates
677  cvp->viewportToCube(lineStart.x(), lineStart.y(), m_startSamp, m_startLine);
678  cvp->viewportToCube(lineEnd.x(), lineEnd.y(), m_endSamp, m_endLine);
679 
680  m_mDist = Null;
681  m_kmDist = Null;
682  double radius = Null;
683  TProjection *tproj = NULL;
684  RingPlaneProjection *rproj = NULL;
686 
687  // Get set for dealing with projection types
688  if (cvp->projection() != NULL) projType = cvp->projection()->projectionType();
689 
690  // Don't write anything if we are outside the cube
691  if ((m_startSamp >= 0.5) && (m_endSamp >= 0.5) &&
692  (m_startLine >= 0.5) && (m_endLine >= 0.5) &&
693  (m_startSamp <= cvp->cubeSamples() + 0.5) &&
694  (m_endSamp <= cvp->cubeSamples() + 0.5) &&
695  (m_startLine <= cvp->cubeLines() + 0.5) &&
696  (m_endLine <= cvp->cubeLines() + 0.5)) {
697  // Check if the image is projected (Projected Images also have camera
698  // except for mosaics)
699  if (cvp->projection() != NULL) {
700  if (cvp->projection()->SetWorld(m_startSamp, m_startLine)) {
701  // If our projection is sky, the lat & lons are switched
702  if (cvp->projection()->IsSky()) {
703  tproj = (TProjection *) cvp->projection();
704  m_startLat = tproj->UniversalLatitude();
705  m_startLon = tproj->UniversalLongitude();
706  }
707  else if (projType == Projection::Triaxial) {
708  tproj = (TProjection *) cvp->projection();
709  m_startLat = tproj->UniversalLatitude();
710  m_startLon = tproj->UniversalLongitude();
711  }
712  else { // RingPlaneProjection
713  rproj = (RingPlaneProjection *) cvp->projection();
714  m_startLat = rproj->UniversalRingRadius();
716  }
717 
718  if (cvp->projection()->SetWorld(m_endSamp, m_endLine)) {
719  // If our projection is sky, the lat & lons are switched
720  if (cvp->projection()->IsSky()) {
721  m_endLat = tproj->UniversalLatitude();
722  m_endLon = tproj->UniversalLongitude();
723  }
724  else if (projType == Projection::Triaxial) {
725  m_endLat = tproj->UniversalLatitude();
726  m_endLon = tproj->UniversalLongitude();
727  } // RingPlaneProjection
728  else {
729  m_endLat = rproj->UniversalRingRadius();
730  m_endLon = rproj->UniversalRingLongitude();
731  }
732  }
733 
734  // Calculate and write out the distance between the two points
735  if (projType != Projection::RingPlane) {
736  radius = tproj->LocalRadius();
737  }
738  else {
739  radius = rproj->RingRadius();
740  }
741  }
742  }
743  // Do we have a camera model?
744  else if (cvp->camera() != NULL &&
746  // Write columns 2-3 (Start lat/lon)
747  m_startLat = cvp->camera()->UniversalLatitude();
749 
750  if (cvp->camera()->SetImage(m_endSamp, m_endLine)) {
751  // Write columns 4-5 (End lat/lon)
752  m_endLat = cvp->camera()->UniversalLatitude();
753  m_endLon = cvp->camera()->UniversalLongitude();
754 
755  radius = cvp->camera()->LocalRadius().meters();
756  }
757  }
758  }
759 
760  // Calculate the pixel difference
761  double lineDif = m_startLine - m_endLine;
762  double sampDif = m_startSamp - m_endSamp;
763  double pixDist = sqrt(lineDif * lineDif + sampDif * sampDif);
764  m_pixDist = pixDist;
765 
766  Latitude startLat(m_startLat, Angle::Degrees);
767  Longitude startLon(m_startLon, Angle::Degrees);
768  Latitude endLat(m_endLat, Angle::Degrees);
769  Longitude endLon(m_endLon, Angle::Degrees);
770  Distance radiusDist(radius, Distance::Meters);
771 
772  SurfacePoint startPoint;
773  SurfacePoint endPoint;
774 
775  if (startLat.isValid() && startLon.isValid() &&
776  endLat.isValid() && endLon.isValid() && radiusDist.isValid()) {
777  startPoint = SurfacePoint(startLat, startLon, radiusDist);
778  endPoint = SurfacePoint(endLat, endLon, radiusDist);
779  }
780 
781  Distance distance = startPoint.GetDistanceToPoint(endPoint, radiusDist);
782 
783  m_mDist = distance.meters();
784  m_kmDist = distance.kilometers();
785  }
786 
787 
790  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
791  rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
792  if (m_unitsComboBox->currentIndex() == 0) {
793  if (m_kmDist == Null) {
794  m_distLineEdit->setText("N/A");
795  }
796  else {
797  m_distLineEdit->setText(QString::number(m_kmDist));
798  }
799  }
800  else if (m_unitsComboBox->currentIndex() == 1) {
801  if (m_mDist == Null) {
802  m_distLineEdit->setText("N/A");
803  }
804  else {
805  m_distLineEdit->setText(QString::number(m_mDist));
806  }
807  }
808  else {
809  m_distLineEdit->setText(QString::number(m_pixDist));
810  }
811  }
812  else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
813  if (m_unitsComboBox->currentIndex() == 0) {
814  m_distLineEdit->setText(QString::number(m_degAngle));
815  }
816  else {
817  m_distLineEdit->setText(QString::number(m_radAngle));
818  }
819  }
820  else {
821  if (m_unitsComboBox->currentIndex() == 0) {
822  if (m_kmArea == Null) {
823  m_distLineEdit->setText("N/A");
824  }
825  else {
826  m_distLineEdit->setText(QString::number(m_kmArea));
827  }
828  }
829  else if (m_unitsComboBox->currentIndex() == 1) {
830  if (m_mArea == Null) {
831  m_distLineEdit->setText("N/A");
832  }
833  else {
834  m_distLineEdit->setText(QString::number(m_mArea));
835  }
836  }
837  else {
838  if (m_pixArea != Null) {
839  m_distLineEdit->setText(QString::number(m_pixArea));
840  }
841  else {
842  m_distLineEdit->setText("N/A");
843  }
844  }
845  }
846  }
847 
848 
856  // cvp->repaint();
857  cvp->update();
858  }
859 
860 
866  m_distLineEdit->clear();
867  }
868 
869 }
870