USGS

Isis 3.0 Object Programmers' Reference

Home

FindTool.cpp
1 #include "FindTool.h"
2 
3 #include <QApplication>
4 #include <QCheckBox>
5 #include <QDialog>
6 #include <QHBoxLayout>
7 #include <QLabel>
8 #include <QMenu>
9 #include <QMenuBar>
10 #include <QMessageBox>
11 #include <QPushButton>
12 #include <QValidator>
13 
14 #include <float.h>
15 
16 #include "Camera.h"
17 #include "Distance.h"
18 #include "Latitude.h"
19 #include "Longitude.h"
20 #include "MainWindow.h"
21 #include "MdiCubeViewport.h"
22 #include "Projection.h"
23 #include "SurfacePoint.h"
24 #include "Target.h"
25 #include "ToolPad.h"
26 #include "UniversalGroundMap.h"
27 #include "Workspace.h"
28 
29 
30 namespace Isis {
36  FindTool::FindTool(QWidget *parent) : Tool(parent) {
37  p_dialog = NULL;
38  p_findPoint = NULL;
39  p_showDialogButton = NULL;
40  p_linkViewportsButton = NULL;
41  p_syncScale = NULL;
42  p_statusEdit = NULL;
43  p_tabWidget = NULL;
44  p_groundTab = NULL;
45  p_imageTab = NULL;
46 
47  p_lat = DBL_MAX;
48  p_lon = DBL_MAX;
49  p_samp = DBL_MAX;
50  p_line = DBL_MAX;
51  p_pointVisible = true;
52 
53  //Set up dialog box
54  createDialog(parent);
55 
56  // Set up find point action
57  p_findPoint = new QAction(parent);
58  p_findPoint->setShortcut(Qt::CTRL + Qt::Key_F);
59  p_findPoint->setText("&Find Point");
60  p_findPoint->setIcon( QPixmap(toolIconDir() + "/find.png") );
61  QString text =
62  "<b>Function:</b> Centers all linked viewports to the selected lat/lon. \
63  The user can click anywhere on the image to have that point centered, or \
64  they can use the shortcut or button to bring up a window that they can \
65  enter a specific lat/lon position into. \
66  <p><b>Shortcut: </b> Ctrl+F </p> \
67  <p><b>Hint: </b> This option will only work if the image has a camera \
68  model or is projected, and will only center the point on images \
69  where the selected lat/lon position exists.</p>";
70  p_findPoint->setWhatsThis(text);
71  p_findPoint->setEnabled(false);
72  connect( p_findPoint, SIGNAL( triggered() ),
73  p_dialog, SLOT( show() ) );
74  }
75 
76  FindTool::~FindTool() {
77  delete p_groundTab->p_latLineEdit->validator();
78  delete p_groundTab->p_lonLineEdit->validator();
79  }
80 
81 
88  p_dialog = new QDialog(parent);
89  p_tabWidget = new QTabWidget(p_dialog);
90  p_dialog->setWindowTitle("Find Latitude/Longitude Coordinate");
91 
92  p_groundTab = new GroundTab();
93  p_imageTab = new ImageTab();
94  p_tabWidget->addTab(p_imageTab, "Image");
95  p_tabWidget->addTab(p_groundTab, "Ground");
96 
97  // Create the action buttons
98  QPushButton *okButton = new QPushButton("Ok");
99  connect( okButton, SIGNAL( clicked() ),
100  this, SLOT( handleOkClicked() ) );
101 
102  QPushButton *recordButton = new QPushButton("Record Point");
103  connect( recordButton, SIGNAL( clicked() ),
104  this, SLOT( handleRecordClicked() ) );
105 
106  QPushButton *closeButton = new QPushButton("Close");
107  connect( closeButton, SIGNAL( clicked() ),
108  p_dialog, SLOT( hide() ) );
109 
110  // Put the buttons in a horizontal orientation
111  QHBoxLayout *actionLayout = new QHBoxLayout();
112  actionLayout->addWidget(okButton);
113  actionLayout->addWidget(recordButton);
114  actionLayout->addWidget(closeButton);
115 
116  QVBoxLayout *dialogLayout = new QVBoxLayout;
117  dialogLayout->addWidget(p_tabWidget);
118  dialogLayout->addLayout(actionLayout);
119  p_dialog->setLayout(dialogLayout);
120  }
121 
122 
128  GroundTab::GroundTab(QWidget *parent) : QWidget(parent) {
129  p_latLineEdit = new QLineEdit();
130  p_latLineEdit->setText("");
131  p_latLineEdit->setValidator( new QDoubleValidator(-90.0, 90.0, 99, parent) );
132  p_lonLineEdit = new QLineEdit();
133  p_lonLineEdit->setText("");
134  p_lonLineEdit->setValidator( new QDoubleValidator(parent) );
135  QLabel *latLabel = new QLabel("Latitude");
136  QLabel *lonLabel = new QLabel("Longitude");
137 
138  // Put the buttons and text field in a gridlayout
139  QGridLayout *gridLayout = new QGridLayout();
140  gridLayout->addWidget(latLabel, 0, 0);
141  gridLayout->addWidget(p_latLineEdit, 0, 1);
142  gridLayout->addWidget(lonLabel, 1, 0);
143  gridLayout->addWidget(p_lonLineEdit, 1, 1);
144  setLayout(gridLayout);
145  }
146 
147 
153  ImageTab::ImageTab(QWidget *parent) : QWidget(parent) {
154  p_sampLineEdit = new QLineEdit();
155  p_sampLineEdit->setText("");
156  p_lineLineEdit = new QLineEdit();
157  p_lineLineEdit->setText("");
158  QLabel *sampleLabel = new QLabel("Sample");
159  QLabel *lineLabel = new QLabel("Line");
160 
161  // Put the buttons and text field in a gridlayout
162  QGridLayout *gridLayout = new QGridLayout();
163  gridLayout->addWidget(sampleLabel, 0, 0);
164  gridLayout->addWidget(p_sampLineEdit, 0, 1);
165  gridLayout->addWidget(lineLabel, 1, 0);
166  gridLayout->addWidget(p_lineLineEdit, 1, 1);
167  setLayout(gridLayout);
168  }
169 
170 
179  QAction *action = new QAction(toolpad);
180  action->setIcon( QPixmap(toolIconDir() + "/find.png") );
181  action->setToolTip("Find (F)");
182  action->setShortcut(Qt::Key_F);
183  QString text =
184  "<b>Function:</b> Find a lat/lon or line/sample coordinate in this cube. \
185  <p><b>Shortcut:</b>F</p> ";
186  action->setWhatsThis(text);
187  return action;
188  }
189 
190 
196  void FindTool::addTo(QMenu *menu) {
197  menu->addAction(p_findPoint);
198  }
199 
200 
208  QWidget *FindTool::createToolBarWidget(QStackedWidget *parent) {
209  QWidget *hbox = new QWidget(parent);
210 
211  p_showDialogButton = new QToolButton(hbox);
212  p_showDialogButton->setIcon( QPixmap(toolIconDir() + "/find.png") );
213  p_showDialogButton->setToolTip("Find Point");
214  QString text =
215  "<b>Function:</b> Centers all linked viewports to the selected lat/lon. \
216  The user can click anywhere on the image to have that point centered, or \
217  they can use the shortcut or button to bring up a window that they can \
218  enter a specific lat/lon position into. \
219  <p><b>Shortcut: </b> Ctrl+F </p> \
220  <p><b>Hint: </b> This option will only work if the image has a camera \
221  model or is projected, and will only center the point on images \
222  where the selected lat/lon position exists.</p>";
223  p_showDialogButton->setWhatsThis(text);
224  connect( p_showDialogButton, SIGNAL( clicked() ),
225  p_dialog, SLOT( show() ) );
226  p_showDialogButton->setAutoRaise(true);
227  p_showDialogButton->setIconSize( QSize(22, 22) );
228 
229  p_syncScale = new QCheckBox("Sync Scale");
230  p_syncScale->setChecked(true);
231  p_syncScale->setToolTip("Synchronize Scale");
232  text = "<b>Function:</b> Syncronizes the scale of all linked viewports.";
233  p_syncScale->setWhatsThis(text);
234 
235  p_linkViewportsButton = new QToolButton(hbox);
236  p_linkViewportsButton->setIcon( QPixmap(toolIconDir() + "/link_valid.png") );
237  p_linkViewportsButton->setToolTip("Link Georeferenced Images");
238  p_linkViewportsButton->setWhatsThis("<b>Function: </b> Links all open images that have\
239  a camera model or are map projections");
240  connect( p_linkViewportsButton, SIGNAL( clicked() ),
241  this, SLOT( handleLinkClicked() ) );
242  p_linkViewportsButton->setAutoRaise(true);
243  p_linkViewportsButton->setIconSize( QSize(22, 22) );
244 
245  p_togglePointVisibleButton = new QToolButton(hbox);
246  p_togglePointVisibleButton->setIcon( QPixmap(toolIconDir() + "/redDot.png") );
247  p_togglePointVisibleButton->setToolTip("Hide red dot");
248  p_togglePointVisibleButton->setCheckable(true);
249  p_togglePointVisibleButton->setChecked(true);
250  connect( p_togglePointVisibleButton, SIGNAL( clicked() ),
251  this, SLOT( togglePointVisible() ) );
252 
253  p_statusEdit = new QLineEdit();
254  p_statusEdit->setReadOnly(true);
255  p_statusEdit->setToolTip("Cube Type");
256  p_statusEdit->setWhatsThis("<b>Function: </b> Displays whether the active cube \
257  is a camera model, projection, both, or none. <p> \
258  <b>Hint: </b> If the cube is 'None' the find tool \
259  will not be active</p>");
260 
261  QHBoxLayout *layout = new QHBoxLayout(hbox);
262  layout->setMargin(0);
263  layout->addWidget(p_statusEdit);
264  layout->addWidget(p_showDialogButton);
265  layout->addWidget(p_linkViewportsButton);
266  layout->addWidget(p_togglePointVisibleButton);
267  layout->addWidget(p_syncScale);
268  layout->addStretch(1);
269  hbox->setLayout(layout);
270 
271  return hbox;
272  }
273 
274 
287  MdiCubeViewport *activeViewport = cubeViewport();
288 
289  if (activeViewport == NULL) {
290  p_linkViewportsButton->setEnabled(false);
291  p_findPoint->setEnabled(false);
292  p_showDialogButton->setEnabled(false);
293  p_syncScale->setEnabled(false);
294  p_statusEdit->setText("None");
295  if ( p_dialog->isVisible() ) {
296  p_dialog->close();
297  }
298  }
299  else {
300  p_findPoint->setEnabled(true);
301  p_showDialogButton->setEnabled(true);
302  p_statusEdit->setText("None");
303 
304  if (cubeViewportList()->size() > 1) {
305  p_linkViewportsButton->setEnabled(true);
306  p_syncScale->setEnabled(true);
307  }
308  else {
309  p_linkViewportsButton->setEnabled(false);
310  p_syncScale->setEnabled(false);
311  }
312 
313  if (activeViewport->camera() != NULL) {
314  p_statusEdit->setText("Camera");
315  if ( cubeViewport()->camera()->HasProjection() ) {
316  p_statusEdit->setText("Both");
317  }
318  }
319  else if (activeViewport->projection() != NULL) {
320  p_statusEdit->setText("Projection");
321  }
322 
323  // from here until the rest of this method we are just updating the
324  // line edits within the dialog
325 
326  UniversalGroundMap *groundMap = activeViewport->universalGroundMap();
327 
328  if (p_samp != DBL_MAX && p_line != DBL_MAX) {
329  if ( groundMap && groundMap->SetImage(p_samp, p_line) ) {
330  QString latStr = QString::number( groundMap->UniversalLatitude() );
331  QString lonStr = QString::number( groundMap->UniversalLongitude() );
332  p_groundTab->p_latLineEdit->setText(latStr);
333  p_groundTab->p_lonLineEdit->setText(lonStr);
334  }
335  else {
336  p_groundTab->p_latLineEdit->setText("");
337  p_groundTab->p_lonLineEdit->setText("");
338  }
339 
340  p_imageTab->p_sampLineEdit->setText( QString::number(p_samp) );
341  p_imageTab->p_lineLineEdit->setText( QString::number(p_line) );
342  }
343  else if (p_lat != DBL_MAX && p_lon != DBL_MAX) {
344  // this should also work for rings (radius, azimuth)
345  if ( groundMap && groundMap->SetUniversalGround(p_lat, p_lon) ) {
346  QString lineStr = QString::number( groundMap->Line() );
347  QString sampStr = QString::number( groundMap->Sample() );
348  p_imageTab->p_lineLineEdit->setText(lineStr);
349  p_imageTab->p_sampLineEdit->setText(sampStr);
350  }
351  else {
352  p_imageTab->p_lineLineEdit->setText("");
353  p_imageTab->p_sampLineEdit->setText("");
354  }
355 
356  p_groundTab->p_latLineEdit->setText( QString::number(p_lat) );
357  p_groundTab->p_lonLineEdit->setText( QString::number(p_lon) );
358  }
359  } // of if activeViewport != NULL
360  }
361 
362 
371  p_samp = DBL_MAX;
372  p_line = DBL_MAX;
373  p_lat = DBL_MAX;
374  p_lon = DBL_MAX;
375 
376  if (p_tabWidget->tabText( p_tabWidget->currentIndex() ) == "Ground") {
377  p_lat = p_groundTab->p_latLineEdit->text().toDouble();
378  p_lon = p_groundTab->p_lonLineEdit->text().toDouble();
379  }
380  else if (p_tabWidget->tabText( p_tabWidget->currentIndex() ) == "Image") {
381  p_line = p_imageTab->p_lineLineEdit->text().toDouble();
382  p_samp = p_imageTab->p_sampLineEdit->text().toDouble();
383  }
384 
386  refresh();
387  updateTool();
388  }
389 
390 
407  double line = p_line;
408  double samp = p_samp;
409 
410  if (p_lat != DBL_MAX && p_lon != DBL_MAX) {
411  MdiCubeViewport *cvp = cubeViewport();
412  UniversalGroundMap *groundMap = cvp->universalGroundMap();
413 
414  if (groundMap) {
415  if ( groundMap->SetUniversalGround(p_lat, p_lon) ) {
416  line = groundMap->Line();
417  samp = groundMap->Sample();
418  }
419  }
420  }
421 
422  if (line != DBL_MAX && samp != DBL_MAX) {
423  int x, y;
424  MdiCubeViewport *cvp = cubeViewport();
425  cvp->cubeToViewport(samp, line, x, y);
426  QPoint p(x, y);
427  emit recordPoint(p);
428  }
429  }
430 
431 
439  void FindTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
440  MdiCubeViewport *activeViewport = cubeViewport();
441  UniversalGroundMap *groundMap = activeViewport->universalGroundMap();
442 
443  double samp, line;
444  activeViewport->viewportToCube(p.x(), p.y(), samp, line);
445 
446  p_samp = DBL_MAX;
447  p_line = DBL_MAX;
448  p_lat = DBL_MAX;
449  p_lon = DBL_MAX;
450 
451  if (groundMap) {
452  if ( groundMap->SetImage(samp, line) ) {
453  p_lat = groundMap->UniversalLatitude();
454  p_lon = groundMap->UniversalLongitude();
455  }
456  }
457  else {
458  p_samp = samp;
459  p_line = line;
460  }
461 
463  refresh();
464  updateTool();
465  }
466 
467 
480  void FindTool::paintViewport(MdiCubeViewport *vp, QPainter *painter) {
481  if ( (vp == cubeViewport() || ( cubeViewport()->isLinked() && vp->isLinked() ) )
482  && p_pointVisible) {
483  double samp = p_samp;
484  double line = p_line;
485 
486  UniversalGroundMap *groundMap = vp->universalGroundMap();
487 
488  if (p_lat != DBL_MAX && p_lon != DBL_MAX && groundMap) {
489  if ( groundMap->SetUniversalGround(p_lat, p_lon) ) {
490  samp = groundMap->Sample();
491  line = groundMap->Line();
492  }
493  }
494 
495  if (samp != DBL_MAX && line != DBL_MAX) {
496  // first find the point
497  int x, y;
498  vp->cubeToViewport(samp, line, x, y);
499 
500  // now that we have the point draw it!
501  QPen pen(Qt::red);
502  pen.setWidth(3);
503  pen.setStyle(Qt::SolidLine);
504  painter->setPen(pen);
505  painter->drawRoundRect(x - 2, y - 2, 4, 4);
506  }
507  }
508  }
509 
510 
513  // toggle the member boolean that specifies visibility
514  p_pointVisible = !p_pointVisible;
515 
516  // update the buttons text
517  if (p_pointVisible) {
518  p_togglePointVisibleButton->setChecked(true);
519  p_togglePointVisibleButton->setToolTip("Hide red dot");
520  }
521  else {
522  p_togglePointVisibleButton->setChecked(false);
523  p_togglePointVisibleButton->setToolTip("Show red dot");
524  }
525 
526  refresh();
527  }
528 
529 
532  MdiCubeViewport *d;
533  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
534  d = ( *( cubeViewportList() ) )[i];
535  if (d->universalGroundMap() != NULL) {
536  d->setLinked(true);
537  }
538  else {
539  d->setLinked(false);
540  }
541  }
542  }
543 
544 
547  MdiCubeViewport *activeViewport = cubeViewport();
548  bool syncScale = p_syncScale->isChecked();
549  // This will be the ground map resolution of the active viewport in meters
550  // per pixel.
551  Distance viewportResolutionToMatch;
552  UniversalGroundMap *groundMap = activeViewport->universalGroundMap();
553 
554  // Equation to match viewports:
555  // otherViewportZoomFactor = activeViewportZoomFactor *
556  // (otherViewportResolution / activeViewportResolution)
557  if (syncScale) {
558  viewportResolutionToMatch = distancePerPixel(activeViewport, p_lat, p_lon);
559  }
560 
561  for (int i = 0; i < cubeViewportList()->size(); i++) {
562  MdiCubeViewport *viewport = ( *( cubeViewportList() ) )[i];
563 
564  if ( viewport == activeViewport ||
565  ( activeViewport->isLinked() && viewport->isLinked() ) ) {
566  groundMap = viewport->universalGroundMap();
567  double otherViewportZoomFactor = viewport->scale();
568 
569  if ( groundMap && !IsSpecial(p_lat) && p_lat != DBL_MAX &&
570  !IsSpecial(p_lon) && p_lon != DBL_MAX &&
571  groundMap->SetUniversalGround(p_lat, p_lon) ) {
572  double samp = groundMap->Sample();
573  double line = groundMap->Line();
574 
575  if ( viewportResolutionToMatch.isValid() ) {
576  Distance otherViewportResolution = distancePerPixel(viewport,
577  p_lat, p_lon);
578  otherViewportZoomFactor = activeViewport->scale() *
579  (otherViewportResolution / viewportResolutionToMatch);
580  }
581 
582  if (p_lat != DBL_MAX && p_lon != DBL_MAX && groundMap) {
583  viewport->setScale(otherViewportZoomFactor, samp, line);
584  }
585  }
586 
587  if (p_line != DBL_MAX && p_samp != DBL_MAX) {
588  viewport->setScale(otherViewportZoomFactor, p_samp, p_line);
589  }
590  }
591  }
592  }
593 
594 
612  double lat, double lon) const {
613  UniversalGroundMap *groundMap = viewport->universalGroundMap();
614  Distance viewportResolution;
615 
616  if ( groundMap && !IsSpecial(lat) && !IsSpecial(lon) &&
617  lat != DBL_MAX && lon != DBL_MAX &&
618  groundMap->SetUniversalGround(lat, lon) ) {
619  // Distance/pixel
620  viewportResolution = Distance(groundMap->Resolution(), Distance::Meters);
621  double samp = groundMap->Sample();
622  double line = groundMap->Line();
623 
624  if ( groundMap->SetImage(samp - 0.5, line - 0.5) ) {
625  double lat1 = groundMap->UniversalLatitude();
626  double lon1 = groundMap->UniversalLongitude();
627 
628  if ( groundMap->SetImage(samp + 0.5, line + 0.5) ) {
629  double lat2 = groundMap->UniversalLatitude();
630  double lon2 = groundMap->UniversalLongitude();
631 
632  double radius = groundMap->HasProjection()?
633  groundMap->Projection()->LocalRadius() :
634  groundMap->Camera()->LocalRadius().meters();
635 
636  SurfacePoint point1( Latitude(lat1, Angle::Degrees),
637  Longitude(lon1, Angle::Degrees),
638  Distance(radius, Distance::Meters) );
639 
640  SurfacePoint point2( Latitude(lat2, Angle::Degrees),
641  Longitude(lon2, Angle::Degrees),
642  Distance(radius, Distance::Meters) );
643 
644  viewportResolution = point1.GetDistanceToPoint(point2);
645  }
646  }
647  }
648 
649  return viewportResolution;
650  }
651 
652 
655  MdiCubeViewport *activeVp = cubeViewport();
656  for (int i = 0; i < cubeViewportList()->size(); i++) {
657  MdiCubeViewport *vp = ( *( cubeViewportList() ) )[i];
658 
659  if ( vp == activeVp || (activeVp->isLinked() && vp->isLinked() ) )
660  vp->viewport()->repaint();
661  }
662  }
663 }