Isis 3 Programmer Reference
QnetTool.cpp
1 #include "QnetTool.h"
2 
3 #include <sstream>
4 #include <vector>
5 #include <iomanip>
6 
7 #include <QComboBox>
8 #include <QFileDialog>
9 #include <QMenuBar>
10 #include <QMessageBox>
11 #include <QScrollBar>
12 #include <QShortcut>
13 #include <QSplitter>
14 #include <QStackedWidget>
15 #include <QtWidgets>
16 #include <QTableWidget>
17 #include <QWhatsThis>
18 
19 #include "QnetDeletePointDialog.h"
20 #include "QnetNewMeasureDialog.h"
21 #include "NewControlPointDialog.h"
22 #include "QnetFixedPointDialog.h"
23 #include "Workspace.h"
24 
25 #include "Application.h"
26 #include "Brick.h"
27 #include "Camera.h"
28 #include "CameraFactory.h"
29 #include "ControlMeasure.h"
30 #include "ControlMeasureLogData.h"
31 #include "ControlNet.h"
32 #include "ControlPoint.h"
33 #include "ControlPointEdit.h"
34 #include "Distance.h"
35 #include "FileName.h"
36 #include "IException.h"
37 #include "Latitude.h"
38 #include "Longitude.h"
39 #include "MainWindow.h"
40 #include "MdiCubeViewport.h"
41 #include "Projection.h"
42 #include "ProjectionFactory.h"
43 #include "Pvl.h"
44 #include "PvlEditDialog.h"
45 #include "SerialNumber.h"
46 #include "SpecialPixel.h"
47 #include "Spice.h"
48 #include "SurfacePoint.h"
49 #include "Target.h"
50 #include "ToolPad.h"
51 #include "UniversalGroundMap.h"
52 #include "ViewportMainWindow.h"
53 
54 using namespace std;
55 
56 namespace Isis {
57 
67  QnetTool::QnetTool (QWidget *parent) : Tool(parent) {
68  m_controlNet = NULL;
69  m_demOpen = false;
70  m_groundOpen = false;
71  m_serialNumberList = NULL;
72  m_templateModified = false;
73 
74  m_controlNet = new ControlNet;
75  m_serialNumberList = new SerialNumberList;
76 
77  if (qobject_cast<Workspace *>(parent)) {
78  m_workspace = qobject_cast<Workspace *>(parent);
79  }
80  else if (qobject_cast<ViewportMainWindow *>(parent)) {
81  m_workspace = qobject_cast<ViewportMainWindow *>(parent)->workspace();
82  }
83  else {
85  tr("Could not find the workspace with the given parent, expected a Workspace or "
86  "ViewportMainWindow."),
87  _FILEINFO_);
88  }
89 
90  createQnetTool(parent);
91  }
92 
93 
94  QnetTool::~QnetTool () {
95  writeSettings();
96 
97  delete m_editPoint;
98  delete m_leftMeasure;
99  delete m_rightMeasure;
100  delete m_measureTable;
101  delete m_measureWindow;
102  }
103 
104 
105 
132 
133  m_qnetTool = new MainWindow("Qnet Tool", parent);
134  m_qnetTool->setObjectName("QnetTool");
135 
136  createActions();
137  createMenus();
138  createToolBars();
139 
140  // create m_pointEditor first since we need to get its templateFileName
141  // later
142  m_pointEditor = new ControlPointEdit(m_controlNet, parent);
143  connect(this, SIGNAL(newControlNetwork(ControlNet *)),
144  m_pointEditor, SIGNAL(newControlNetwork(ControlNet *)));
145  connect(this,
146  SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)),
147  m_pointEditor,
148  SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)));
149  connect(m_pointEditor, SIGNAL(measureSaved()), this, SLOT(measureSaved()));
150  connect(this, SIGNAL(measureChanged()),
151  m_pointEditor, SLOT(colorizeSaveButton()));
152 
153  QPushButton *addMeasure = new QPushButton("Add Measure(s) to Point");
154  addMeasure->setShortcut(Qt::Key_A);
155  addMeasure->setToolTip("Add a new measure to the edit control point. "
156  "<strong>Shortcut: A</strong>");
157  addMeasure->setWhatsThis("This allows a new control measure to be added "
158  "to the currently edited control point. A selection "
159  "box with all cubes from the input list will be "
160  "displayed with those that intersect with the "
161  "control point highlighted.");
162  connect(addMeasure, SIGNAL(clicked()), this, SLOT(addMeasure()));
163 
164  m_savePoint = new QPushButton ("Save Point");
165  m_savePoint->setShortcut(Qt::Key_P);
166  m_savePoint->setToolTip("Save the edit control point to the control network. "
167  "<strong>Shortcut: P</strong>");
168  m_savePoint->setWhatsThis("Save the edit control point to the control "
169  "network which is loaded into memory in its entirety. "
170  "When a control point is selected for editing, "
171  "a copy of the point is made so that the original control "
172  "point remains in the network.");
173  m_saveDefaultPalette = m_savePoint->palette();
174  connect (m_savePoint,SIGNAL(clicked()),this,SLOT(savePoint()));
175 
176  QHBoxLayout * addMeasureLayout = new QHBoxLayout;
177  addMeasureLayout->addWidget(addMeasure);
178  addMeasureLayout->addWidget(m_savePoint);
179 // addMeasureLayout->addStretch();
180 
181  m_templateFileNameLabel = new QLabel("Template File: " +
182  m_pointEditor->templateFileName());
183  m_templateFileNameLabel->setToolTip("Sub-pixel registration template File.");
184 // QString patternMatchDoc =
185 // FileName("$ISISROOT/doc/documents/PatternMatch/PatternMatch.html").fileName();
186 // m_templateFileNameLabel->setOpenExternalLinks(true);
187  m_templateFileNameLabel->setWhatsThis("FileName of the sub-pixel "
188  "registration template. Refer to $ISISROOT/doc/documents/"
189  "PatternMatch/PatternMatch.html for a description of the "
190  "contents of this file.");
191 
192  m_groundFileNameLabel = new QLabel("Ground Source File: ");
193  m_groundFileNameLabel->setToolTip("Cube used to create ground control "
194  "points, either Fixed or Constrained.");
195  m_groundFileNameLabel->setWhatsThis("This cube is used to create ground "
196  "control points, Fixed or Constrained. This may "
197  "be a Dem, a shaded relief version of a Dem, "
198  "a projected basemap or an unprojected cube with "
199  "corrected camera pointing. This will be used "
200  "to set the apriori latitude, longitude.");
201  m_radiusFileNameLabel = new QLabel("Radius Source: ");
202  m_radiusFileNameLabel->setToolTip("Dem used to set the radius of ground "
203  "control points, Fixed or Constrained. This must "
204  "be a Dem and is strictly used to set the apriori "
205  "radius for ground control points.");
206 
207  QVBoxLayout * centralLayout = new QVBoxLayout;
208 
209  centralLayout->addWidget(m_templateFileNameLabel);
210  centralLayout->addWidget(m_groundFileNameLabel);
211  centralLayout->addWidget(m_radiusFileNameLabel);
212  centralLayout->addWidget(createTopSplitter());
213  centralLayout->addStretch();
214  centralLayout->addWidget(m_pointEditor);
215  centralLayout->addLayout(addMeasureLayout);
216  QWidget * centralWidget = new QWidget;
217  centralWidget->setLayout(centralLayout);
218 
219  QScrollArea *scrollArea = new QScrollArea();
220  scrollArea->setObjectName("QnetToolScroll");
221  scrollArea->setWidget(centralWidget);
222  scrollArea->setWidgetResizable(true);
223  centralWidget->adjustSize();
224  m_qnetTool->setCentralWidget(scrollArea);
225 // m_qnetTool->setCentralWidget(centralWidget);
226 
227 
228  connect(this, SIGNAL(editPointChanged(QString)),
229  this, SLOT(paintAllViewports(QString)));
230 
231  readSettings();
232  }
233 
234 
237 
238  QHBoxLayout * measureLayout = new QHBoxLayout;
239  measureLayout->addWidget(createLeftMeasureGroupBox());
240  measureLayout->addWidget(createRightMeasureGroupBox());
241 
242  QVBoxLayout * groupBoxesLayout = new QVBoxLayout;
243  groupBoxesLayout->addWidget(createControlPointGroupBox());
244  groupBoxesLayout->addStretch();
245  groupBoxesLayout->addLayout(measureLayout);
246 
247  QWidget * groupBoxesWidget = new QWidget;
248  groupBoxesWidget->setLayout(groupBoxesLayout);
249 
251 
252  QSplitter * topSplitter = new QSplitter;
253  topSplitter->addWidget(groupBoxesWidget);
254  topSplitter->addWidget(m_templateEditorWidget);
255  topSplitter->setStretchFactor(0, 4);
256  topSplitter->setStretchFactor(1, 3);
257 
258  m_templateEditorWidget->hide();
259 
260  return topSplitter;
261  }
262 
263 
266 
267  // create left vertical layout
268  m_ptIdValue = new QLabel;
269  m_pointType = new QComboBox;
270  for (int i=0; i<ControlPoint::PointTypeCount; i++) {
271  m_pointType->insertItem(i, ControlPoint::PointTypeToString(
273  }
274  QHBoxLayout *pointTypeLayout = new QHBoxLayout;
275  QLabel *pointTypeLabel = new QLabel("PointType:");
276  pointTypeLayout->addWidget(pointTypeLabel);
277  pointTypeLayout->addWidget(m_pointType);
278  connect(m_pointType, SIGNAL(activated(int)),
279  this, SLOT(setPointType(int)));
280  m_numMeasures = new QLabel;
281  m_pointAprioriLatitude = new QLabel;
282  m_pointAprioriLongitude = new QLabel;
283  m_pointAprioriRadius = new QLabel;
284  m_pointAprioriLatitudeSigma = new QLabel;
285  m_pointAprioriLongitudeSigma = new QLabel;
286  m_pointAprioriRadiusSigma = new QLabel;
287  QVBoxLayout * leftLayout = new QVBoxLayout;
288  leftLayout->addWidget(m_ptIdValue);
289  leftLayout->addLayout(pointTypeLayout);
290  leftLayout->addWidget(m_pointAprioriLatitude);
291  leftLayout->addWidget(m_pointAprioriLongitude);
292  leftLayout->addWidget(m_pointAprioriRadius);
293  leftLayout->addWidget(m_pointAprioriLatitudeSigma);
294  leftLayout->addWidget(m_pointAprioriLongitudeSigma);
295  leftLayout->addWidget(m_pointAprioriRadiusSigma);
296 
297  // create right vertical layout's top layout
298  m_lockPoint = new QCheckBox("Edit Lock Point");
299  connect(m_lockPoint, SIGNAL(clicked(bool)), this, SLOT(setLockPoint(bool)));
300  m_ignorePoint = new QCheckBox("Ignore Point");
301  connect(m_ignorePoint, SIGNAL(clicked(bool)),
302  this, SLOT(setIgnorePoint(bool)));
303  connect(this, SIGNAL(ignorePointChanged()), m_ignorePoint, SLOT(toggle()));
304  m_pointLatitude = new QLabel;
305  m_pointLongitude = new QLabel;
306  m_pointRadius = new QLabel;
307 
308  QVBoxLayout * rightLayout = new QVBoxLayout;
309  rightLayout->addWidget(m_numMeasures);
310  rightLayout->addWidget(m_lockPoint);
311  rightLayout->addWidget(m_ignorePoint);
312  rightLayout->addWidget(m_pointLatitude);
313  rightLayout->addWidget(m_pointLongitude);
314  rightLayout->addWidget(m_pointRadius);
315 
316 
317  QHBoxLayout * mainLayout = new QHBoxLayout;
318  mainLayout->addLayout(leftLayout);
319  mainLayout->addStretch();
320  mainLayout->addLayout(rightLayout);
321 
322  // create the groupbox
323  QGroupBox * groupBox = new QGroupBox("Control Point");
324  groupBox->setLayout(mainLayout);
325 
326  return groupBox;
327  }
328 
329 
332 
333  m_leftCombo = new QComboBox;
334  m_leftCombo->view()->installEventFilter(this);
335  m_leftCombo->setToolTip("Choose left control measure");
336  m_leftCombo->setWhatsThis("Choose left control measure identified by "
337  "cube filename.");
338  connect(m_leftCombo, SIGNAL(activated(int)),
339  this, SLOT(selectLeftMeasure(int)));
340  m_lockLeftMeasure = new QCheckBox("Edit Lock Measure");
341  connect(m_lockLeftMeasure, SIGNAL(clicked(bool)),
342  this, SLOT(setLockLeftMeasure(bool)));
343  m_ignoreLeftMeasure = new QCheckBox("Ignore Measure");
344  connect(m_ignoreLeftMeasure, SIGNAL(clicked(bool)),
345  this, SLOT(setIgnoreLeftMeasure(bool)));
346  connect(this, SIGNAL(ignoreLeftChanged()),
347  m_ignoreLeftMeasure, SLOT(toggle()));
348  m_leftReference = new QLabel();
349  m_leftMeasureType = new QLabel();
350  m_leftSampError = new QLabel();
351  m_leftSampError->setToolTip("<strong>Jigsaw</strong> sample residual.");
352  m_leftSampError->setWhatsThis("This is the sample residual for the left "
353  "measure calculated by the application, "
354  "<strong>jigsaw</strong>.");
355  m_leftLineError = new QLabel();
356  m_leftLineError->setToolTip("<strong>Jigsaw</strong> line residual.");
357  m_leftLineError->setWhatsThis("This is the line residual for the left "
358  "measure calculated by the application, "
359  "<strong>jigsaw</strong>.");
360  m_leftSampShift = new QLabel();
361  m_leftSampShift->setToolTip("Sample shift between apriori and current");
362  m_leftSampShift->setWhatsThis("The shift between the apriori sample and "
363  "the current sample. The apriori sample is set "
364  "when creating a new measure.");
365  m_leftLineShift = new QLabel();
366  m_leftLineShift->setToolTip("Line shift between apriori and current");
367  m_leftLineShift->setWhatsThis("The shift between the apriori line and "
368  "the current line. The apriori line is set "
369  "when creating a new measure.");
370  m_leftGoodness = new QLabel();
371  m_leftGoodness->setToolTip("Goodness of Fit result from sub-pixel "
372  "registration.");
373  m_leftGoodness->setWhatsThis("Resulting Goodness of Fit from sub-pixel "
374  "registration.");
375  QVBoxLayout * leftLayout = new QVBoxLayout;
376  leftLayout->addWidget(m_leftCombo);
377  leftLayout->addWidget(m_lockLeftMeasure);
378  leftLayout->addWidget(m_ignoreLeftMeasure);
379  leftLayout->addWidget(m_leftReference);
380  leftLayout->addWidget(m_leftMeasureType);
381  leftLayout->addWidget(m_leftSampError);
382  leftLayout->addWidget(m_leftLineError);
383  leftLayout->addWidget(m_leftSampShift);
384  leftLayout->addWidget(m_leftLineShift);
385  leftLayout->addWidget(m_leftGoodness);
386 
387  QGroupBox * leftGroupBox = new QGroupBox("Left Measure");
388  leftGroupBox->setLayout(leftLayout);
389 
390  return leftGroupBox;
391  }
392 
393 
404 
405  // create widgets for the right groupbox
406  m_rightCombo = new QComboBox;
407  m_rightCombo->view()->installEventFilter(this);
408 
409  // Attach shortcuts to Qnet Tool's window for selecting right measures
410  // Note: Qt handles this memory for us since m_qnetTool is the parent of these shortcuts
411  QShortcut *nextMeasure = new QShortcut(Qt::Key_PageDown, m_qnetTool);
412  connect(nextMeasure, SIGNAL(activated()), this, SLOT(nextRightMeasure()));
413  QShortcut *prevMeasure = new QShortcut(Qt::Key_PageUp, m_qnetTool);
414  connect(prevMeasure, SIGNAL(activated()), this, SLOT(previousRightMeasure()));
415 
416  m_rightCombo->setToolTip("Choose right control measure. "
417  "<strong>Shortcuts: PageUp/PageDown</strong>");
418  m_rightCombo->setWhatsThis("Choose right control measure identified by "
419  "cube filename. "
420  "Note: PageUp selects previous measure; "
421  "PageDown selects next meausure.");
422  connect(m_rightCombo, SIGNAL(activated(int)),
423  this, SLOT(selectRightMeasure(int)));
424  m_lockRightMeasure = new QCheckBox("Edit Lock Measure");
425  connect(m_lockRightMeasure, SIGNAL(clicked(bool)),
426  this, SLOT(setLockRightMeasure(bool)));
427  m_ignoreRightMeasure = new QCheckBox("Ignore Measure");
428  connect(m_ignoreRightMeasure, SIGNAL(clicked(bool)),
429  this, SLOT(setIgnoreRightMeasure(bool)));
430  connect(this, SIGNAL(ignoreRightChanged()),
431  m_ignoreRightMeasure, SLOT(toggle()));
432  m_rightReference = new QLabel();
433  m_rightMeasureType = new QLabel();
434  m_rightSampError = new QLabel();
435  m_rightSampError->setToolTip("<strong>Jigsaw</strong> sample residual.");
436  m_rightSampError->setWhatsThis("This is the sample residual for the right "
437  "measure which was calculated by the application, "
438  "<strong>jigsaw</strong>.");
439  m_rightLineError = new QLabel();
440  m_rightLineError->setToolTip("<strong>Jigsaw</strong> line residual.");
441  m_rightLineError->setWhatsThis("This is the line residual for the right "
442  "measure which was calculated by the application, "
443  "<strong>jigsaw</strong>.");
444  m_rightSampShift = new QLabel();
445  m_rightSampShift->setToolTip(m_leftSampShift->toolTip());
446  m_rightSampShift->setWhatsThis(m_leftSampShift->whatsThis());
447  m_rightLineShift = new QLabel();
448  m_rightLineShift->setToolTip(m_leftLineShift->toolTip());
449  m_rightLineShift->setWhatsThis(m_leftLineShift->whatsThis());
450  m_rightGoodness = new QLabel();
451  m_rightGoodness->setToolTip(m_leftGoodness->toolTip());
452  m_rightGoodness->setWhatsThis(m_leftGoodness->whatsThis());
453 
454  // create right groupbox
455  QVBoxLayout * rightLayout = new QVBoxLayout;
456  rightLayout->addWidget(m_rightCombo);
457  rightLayout->addWidget(m_lockRightMeasure);
458  rightLayout->addWidget(m_ignoreRightMeasure);
459  rightLayout->addWidget(m_rightReference);
460  rightLayout->addWidget(m_rightMeasureType);
461  rightLayout->addWidget(m_rightSampError);
462  rightLayout->addWidget(m_rightLineError);
463  rightLayout->addWidget(m_rightSampShift);
464  rightLayout->addWidget(m_rightLineShift);
465  rightLayout->addWidget(m_rightGoodness);
466 
467  QGroupBox * rightGroupBox = new QGroupBox("Right Measure");
468  rightGroupBox->setLayout(rightLayout);
469 
470  return rightGroupBox;
471  }
472 
473 
476 
477  QToolBar *toolBar = new QToolBar("Template Editor ToolBar");
478 
479  toolBar->addAction(m_openTemplateFile);
480  toolBar->addSeparator();
481  toolBar->addAction(m_saveTemplateFile);
482  toolBar->addAction(m_saveTemplateFileAs);
483 
484  m_templateEditor = new QTextEdit;
485  connect(m_templateEditor, SIGNAL(textChanged()), this,
486  SLOT(setTemplateModified()));
487 
488  QVBoxLayout *mainLayout = new QVBoxLayout;
489  mainLayout->addWidget(toolBar);
490  mainLayout->addWidget(m_templateEditor);
491 
492  m_templateEditorWidget = new QWidget;
493  m_templateEditorWidget->setLayout(mainLayout);
494  }
495 
496 
497 
506  m_openGround = new QAction(m_qnetTool);
507  m_openGround->setText("Open &Ground Source");
508  m_openGround->setToolTip("Open a ground source for choosing ground control "
509  "points");
510  m_openGround->setStatusTip("Open a ground source for choosing ground "
511  "control points");
512  QString whatsThis =
513  "<b>Function:</b> Open and display a ground source for choosing "
514  "ground control points, both Fixed and Constrained."
515  "This cube can be a level1, level2 or dem cube.";
516  m_openGround->setWhatsThis(whatsThis);
517  connect (m_openGround,SIGNAL(triggered()),this,SLOT(openGround()));
518 
519  m_openDem = new QAction(m_qnetTool);
520  m_openDem->setText("Open &Radius Source");
521  m_openDem->setToolTip("Open radius source file for ground control points");
522  m_openDem->setStatusTip("Open radius source file for ground control points");
523  whatsThis =
524  "<b>Function:</b> Open a DEM for determining the radius when "
525  "choosing ground control points. This is not the file that will be "
526  "displayed for visually picking points. This is strictly used to "
527  "determine the radius value for ground control points.";
528  m_openDem->setWhatsThis(whatsThis);
529  connect (m_openDem,SIGNAL(triggered()),this,SLOT(openDem()));
530 
531  m_saveNet = new QAction(QIcon(toolIconDir() + "/filesave.png"), "Save Control Network ...",
532  m_qnetTool);
533  m_saveNet->setShortcut(Qt::CTRL + Qt::Key_S);
534  m_saveNet->setToolTip("Save current control network");
535  m_saveNet->setStatusTip("Save current control network");
536  whatsThis = "<b>Function:</b> Saves the current <i>"
537  "control network</i>";
538  m_saveNet->setWhatsThis(whatsThis);
539  connect(m_saveNet, SIGNAL(triggered()), this, SLOT(saveNet()));
540 
541  m_saveAsNet = new QAction(QIcon(toolIconDir() + "/filesaveas.png"), "Save Control Network &As...",
542  m_qnetTool);
543  m_saveAsNet->setToolTip("Save current control network to chosen file");
544  m_saveAsNet->setStatusTip("Save current control network to chosen file");
545  whatsThis = "<b>Function:</b> Saves the current <i>"
546  "control network</i> under chosen filename";
547  m_saveAsNet->setWhatsThis(whatsThis);
548  connect(m_saveAsNet, SIGNAL(triggered()), this, SLOT(saveAsNet()));
549 
550  m_closeQnetTool = new QAction(QIcon(toolIconDir() + "/fileclose.png"), "&Close", m_qnetTool);
551  m_closeQnetTool->setToolTip("Close this window");
552  m_closeQnetTool->setStatusTip("Close this window");
553  m_closeQnetTool->setShortcut(Qt::ALT + Qt::Key_F4);
554  whatsThis = "<b>Function:</b> Closes the Qnet Tool window for this point "
555  "<p><b>Shortcut:</b> Alt+F4 </p>";
556  m_closeQnetTool->setWhatsThis(whatsThis);
557  connect(m_closeQnetTool, SIGNAL(triggered()), m_qnetTool, SLOT(close()));
558 
559  m_showHideTemplateEditor = new QAction(QIcon(toolIconDir() + "/view_text.png"),
560  "&View/edit registration template", m_qnetTool);
561  m_showHideTemplateEditor->setCheckable(true);
562  m_showHideTemplateEditor->setToolTip("View and/or edit the registration "
563  "template");
564  m_showHideTemplateEditor->setStatusTip("View and/or edit the registration "
565  "template");
566  whatsThis = "<b>Function:</b> Displays the curent registration template. "
567  "The user may edit and save changes under a chosen filename.";
568  m_showHideTemplateEditor->setWhatsThis(whatsThis);
569  connect(m_showHideTemplateEditor, SIGNAL(triggered()), this,
570  SLOT(showHideTemplateEditor()));
571 
572  m_saveChips = new QAction(QIcon(toolIconDir() + "/savechips.png"), "Save registration chips",
573  m_qnetTool);
574  m_saveChips->setToolTip("Save registration chips");
575  m_saveChips->setStatusTip("Save registration chips");
576  whatsThis = "<b>Function:</b> Save registration chips to file. "
577  "Each chip: pattern, search, fit will be saved to a separate file.";
578  m_saveChips->setWhatsThis(whatsThis);
579  connect(m_saveChips, SIGNAL(triggered()), this, SLOT(saveChips()));
580 
581  m_openTemplateFile = new QAction(QIcon(toolIconDir() + "/fileopen.png"), "&Open registration "
582  "template", m_qnetTool);
583  m_openTemplateFile->setToolTip("Set registration template");
584  m_openTemplateFile->setStatusTip("Set registration template");
585  whatsThis = "<b>Function:</b> Allows user to select a new file to set as "
586  "the registration template";
587  m_openTemplateFile->setWhatsThis(whatsThis);
588  connect(m_openTemplateFile, SIGNAL(triggered()), this, SLOT(openTemplateFile()));
589 
590  m_saveTemplateFile = new QAction(QIcon(toolIconDir() + "/filesave.png"), "&Save template file",
591  m_qnetTool);
592  m_saveTemplateFile->setToolTip("Save the template file");
593  m_saveTemplateFile->setStatusTip("Save the template file");
594  m_saveTemplateFile->setWhatsThis("Save the registration template file");
595  connect(m_saveTemplateFile, SIGNAL(triggered()), this,
596  SLOT(saveTemplateFile()));
597 
598  m_saveTemplateFileAs = new QAction(QIcon(toolIconDir() + "/filesaveas.png"), "&Save template as...",
599  m_qnetTool);
600  m_saveTemplateFileAs->setToolTip("Save the template file as");
601  m_saveTemplateFileAs->setStatusTip("Save the template file as");
602  m_saveTemplateFileAs->setWhatsThis("Save the registration template file as");
603  connect(m_saveTemplateFileAs, SIGNAL(triggered()), this,
604  SLOT(saveTemplateFileAs()));
605 
606  m_whatsThis = new QAction(QIcon(FileName(
607  "$base/icons/contexthelp.png").expanded()),"&Whats's This", m_qnetTool);
608  m_whatsThis->setShortcut(Qt::SHIFT | Qt::Key_F1);
609  m_whatsThis->setToolTip("Activate What's This and click on items on "
610  "user interface to see more information.");
611  connect(m_whatsThis, SIGNAL(triggered()), this, SLOT(enterWhatsThisMode()));
612 
613  }
614 
615 
616 
627 
628  QMenu *fileMenu = m_qnetTool->menuBar()->addMenu("&File");
629  fileMenu->addAction(m_openGround);
630  fileMenu->addAction(m_openDem);
631  fileMenu->addAction(m_saveNet);
632  fileMenu->addAction(m_saveAsNet);
633  fileMenu->addAction(m_closeQnetTool);
634 
635  QMenu * regMenu = m_qnetTool->menuBar()->addMenu("&Registration");
636  regMenu->addAction(m_openTemplateFile);
637  regMenu->addAction(m_showHideTemplateEditor);
638  regMenu->addAction(m_saveChips);
639 
640  QMenu *helpMenu = m_qnetTool->menuBar()->addMenu("&Help");
641  helpMenu->addAction(m_whatsThis);
642  }
643 
644 
645  void QnetTool::createToolBars() {
646 
647  toolBar = new QToolBar;
648  toolBar->setObjectName("TemplateEditorToolBar");
649  toolBar->setFloatable(false);
650  toolBar->addAction(m_saveNet);
651  toolBar->addSeparator();
652  toolBar->addAction(m_showHideTemplateEditor);
653  toolBar->addAction(m_saveChips);
654  toolBar->addAction(m_whatsThis);
655 
656  m_qnetTool->addToolBar(Qt::TopToolBarArea, toolBar);
657  }
658 
659 
660 
725  // Read original measures from the network for comparison with measures
726  // that have been edited
727  ControlMeasure *origLeftMeasure =
728  m_editPoint->GetMeasure(m_leftMeasure->GetCubeSerialNumber());
729  ControlMeasure *origRightMeasure =
730  m_editPoint->GetMeasure(m_rightMeasure->GetCubeSerialNumber());
731 
732  if (m_editPoint->IsIgnored()) {
733  QString message = "You are saving changes to a measure on an ignored ";
734  message += "point. Do you want to set Ignore = False on the point and ";
735  message += "both measures?";
736  switch (QMessageBox::question(m_qnetTool, "Qnet Tool Save Measure",
737  message, "&Yes", "&No", 0, 0)) {
738  // Yes: set Ignore=false for the point and measures and save point
739  case 0:
740  m_editPoint->SetIgnored(false);
741  emit ignorePointChanged();
742  if (m_leftMeasure->IsIgnored()) {
743  m_leftMeasure->SetIgnored(false);
744  emit ignoreLeftChanged();
745  }
746  if (m_rightMeasure->IsIgnored()) {
747  m_rightMeasure->SetIgnored(false);
748  emit ignoreRightChanged();
749  }
750  // No: keep Ignore=true and save measure
751  case 1:
752  break;
753 
754  }
755  }
756  if (origRightMeasure->IsIgnored() && m_rightMeasure->IsIgnored()) {
757  QString message = "You are saving changes to an ignored measure. ";
758  message += "Do you want to set Ignore = False on the right measure?";
759  switch(QMessageBox::question(m_qnetTool, "Qnet Tool Save Measure",
760  message, "&Yes", "&No", 0, 0)){
761  // Yes: set Ignore=false for the right measure and save point
762  case 0:
763  m_rightMeasure->SetIgnored(false);
764  emit ignoreRightChanged();
765  // No: keep Ignore=true and save point
766  case 1:
767  break;
768  }
769  }
770 
771  // Only check reference if point contains explicit reference. Otherwise,
772  // there has not been a reference set, set the measure on the left as the reference.
773  if (m_editPoint->IsReferenceExplicit()) {
774  if (m_editPoint->IsEditLocked()) {
775  QString message = "This control point is edit locked. The Apriori latitude, longitude and ";
776  message += "radius cannot be updated. You must first unlock the point by clicking the ";
777  message += "check box above labeled \"Edit Lock Point\".";
778  QMessageBox::warning(m_qnetTool, "Point Locked", message);
779  return;
780  }
781  // If user does not want to change the reference then don't update the measure
782  if (!checkReference()) {
783  return;
784  }
785  }
786  else if (m_leftMeasure->GetCubeSerialNumber() != m_groundSN) {
787  m_editPoint->SetRefMeasure(m_leftMeasure->GetCubeSerialNumber());
788  }
789 
790  // If this is a fixed or constrained point, and the right measure is the ground source,
791  // update the lat,lon,radius. Only the right measure can be moved, so only need to update
792  // position if the ground measure is loaded on the right.
793  //
794  // If point is locked and it is not a new point, print error
795  // TODO:: Only update if the measure moved
796  if (m_editPoint->GetType() != ControlPoint::Free && (m_groundOpen &&
797  m_rightMeasure->GetCubeSerialNumber() == m_groundSN)) {
798  if (m_editPoint->IsEditLocked() && m_controlNet->ContainsPoint(m_editPoint->GetId())) {
799  QString message = "This control point is edit locked. The Apriori latitude, longitude and ";
800  message += "radius cannot be updated. You must first unlock the point by clicking the ";
801  message += "check box above labeled \"Edit Lock Point\".";
802  QMessageBox::warning(m_qnetTool, "Point Locked", message);
803  return;
804  }
805  if (m_leftMeasure->IsIgnored()) {
806  QString message = "This is a Constrained or Fixed point and the reference measure is ";
807  message += "Ignored. Unset the Ignore flag on the reference measure before saving.";
808  QMessageBox::warning(m_qnetTool, "Point Locked", message);
809  return;
810  }
811  updateGroundPosition();
812  }
813 
814  // Save the right measure and left (if ignore or edit lock flag changed) to
815  // the editPoint The Ignore flag is the only thing that can change on the left
816  // measure.
817  m_rightMeasure->SetChooserName(Application::UserName());
818  *origRightMeasure = *m_rightMeasure;
819 
820  // Only save the left measure if the ignore flag or editLock has changed
821  if (m_leftMeasure->IsIgnored() != origLeftMeasure->IsIgnored() ||
822  m_leftMeasure->IsEditLocked() != origLeftMeasure->IsEditLocked()) {
823  m_leftMeasure->SetChooserName(Application::UserName());
824  *origLeftMeasure = *m_leftMeasure;
825  }
826 
827  // If left measure == right measure, update left
828  if (m_leftMeasure->GetCubeSerialNumber() ==
829  m_rightMeasure->GetCubeSerialNumber()) {
830  *m_leftMeasure = *m_rightMeasure;
831  // Update left measure of pointEditor
832  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube.data(),
833  m_editPoint->GetId());
834  }
835 
836  // Change Save Point button text to red
838 
839  editPointChanged(m_editPoint->GetId());
840 
841  // Update measure info
845  }
846 
847 
848 
865 
866  // Check if ControlPoint has reference measure, if reference Measure is
867  // not the same measure that is on the left chip viewport, set left
868  // measure as reference.
869  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
870  if ( (m_leftMeasure->GetCubeSerialNumber() != m_groundSN) &&
871  (refMeasure->GetCubeSerialNumber() != m_leftMeasure->GetCubeSerialNumber()) ) {
872  QString message = "This point already contains a reference measure. ";
873  message += "Would you like to replace it with the measure on the left?";
874  int response = QMessageBox::question(m_qnetTool,
875  "Qnet Tool Save Measure", message,
876  QMessageBox::Yes | QMessageBox::No,
877  QMessageBox::Yes);
878  // Replace reference measure
879  if (response == QMessageBox::Yes) {
880  // Update measure file combo boxes: old reference normal font,
881  // new reference bold font
882  QString file = m_serialNumberList->fileName(m_leftMeasure->GetCubeSerialNumber());
883  QString fname = FileName(file).name();
884  int iref = m_leftCombo->findText(fname);
885 
886  // Save normal font from new reference measure
887  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
888  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
889  iref = m_rightCombo->findText(fname);
890  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
891 
892  file = m_serialNumberList->fileName(refMeasure->GetCubeSerialNumber());
893  fname = FileName(file).name();
894  iref = m_leftCombo->findText(fname);
895  m_leftCombo->setItemData(iref,font,Qt::FontRole);
896  iref = m_rightCombo->findText(fname);
897  m_rightCombo->setItemData(iref,font,Qt::FontRole);
898 
899  m_editPoint->SetRefMeasure(m_leftMeasure->GetCubeSerialNumber());
900  // Update reference measure to new reference measure
901  refMeasure = m_editPoint->GetRefMeasure();
902  }
903  // ??? Need to set rest of measures to Candidate and add more warning. ???//
904  }
905 
906  // If the right measure is the reference, make sure they really want
907  // to move the reference.
908  if (refMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
909  QString message = "You are making a change to the reference measure. You ";
910  message += "may need to move all of the other measures to match the new ";
911  message += " coordinate of the reference measure. Do you really want to ";
912  message += " change the reference measure? ";
913  switch(QMessageBox::question(m_qnetTool, "Qnet Tool Save Measure",
914  message, "&Yes", "&No", 0, 0)){
915  // Yes: Save measure
916  case 0:
917  return true;
918  // No: keep original reference, return ChipViewports to previous states
919  case 1:
920  selectRightMeasure(m_rightCombo->currentIndex());
921  selectLeftMeasure(m_leftCombo->currentIndex());
922  return false;
923  }
924  }
925  return true;
926  }
927 
928 
929 
930  /*
931  * Update the position of ground point
932  *
933  * @author 2012-04-26 Tracie Sucharski - moved functionality from measureSaved
934  *
935  * @internal
936  *
937  */
938  void QnetTool::updateGroundPosition() {
939 
940  // TODO: If groundSource file opened does not match the SurfacePoint Source
941  // file, print warning.
942 
943  // This method only called if ground measure is on the right. Use ground measure to update
944  // apriori surface point.
945  ControlMeasure *groundMeasure = m_rightMeasure;
946  if (!m_groundGmap->SetImage(groundMeasure->GetSample(),
947  groundMeasure->GetLine())) {
948  // TODO : should never happen, either add error check or
949  // get rid of
950  }
951 
952  double lat = m_groundGmap->UniversalLatitude();
953  double lon = m_groundGmap->UniversalLongitude();
954 // cout<<"lat = "<<setprecision(15)<<lat<<endl;
955 // cout<<"lon = "<<lon<<endl;
956  double radius;
957  // Update radius, order of precedence
958  // 1. If a dem has been opened, read radius from dem.
959  // 2. Get radius from reference measure
960  // If image has shape model, radius will come from shape model
961  //
962  if (m_demOpen) {
963  radius = demRadius(lat,lon);
964  if (radius == Null) {
965  QString msg = "Could not read radius from DEM, will default to "
966  "local radius of reference measure.";
967  QMessageBox::warning(m_qnetTool, "Warning", msg);
968  if (m_editPoint->GetRefMeasure()->Camera()->SetGround(
969  Latitude(lat, Angle::Degrees), Longitude(lon, Angle::Degrees))) {
970  radius =
971  m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
972  m_editPoint->SetAprioriRadiusSource(
973  ControlPoint::RadiusSource::None);
974  //m_editPoint->SetAprioriRadiusSourceFile(m_radiusSourceFile);
975  }
976  else {
977  QString message = "Error trying to get radius at this pt. "
978  "Lat/Lon does not fall on the reference measure. "
979  "Cannot save this measure.";
980  QMessageBox::critical(m_qnetTool,"Error",message);
981  return;
982  }
983  }
984  m_editPoint->SetAprioriRadiusSource(m_groundRadiusSource);
985  m_editPoint->SetAprioriRadiusSourceFile(m_radiusSourceFile);
986  }
987  else {
988  // Get radius from reference image
989  if (m_editPoint->GetRefMeasure()->Camera()->SetGround(
990  Latitude(lat, Angle::Degrees), Longitude(lon, Angle::Degrees))) {
991  radius =
992  m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
993 // cout.width(15);
994 // cout.precision(4);
995 // cout<<"Camera Radius = "<<fixed<<radius<<endl;
996  //radius = m_groundGmap->Projection()->LocalRadius();
997  }
998  else {
999  QString message = "Error trying to get radius at this pt. "
1000  "Lat/Lon does not fall on the reference measure. "
1001  "Cannot save this measure.";
1002  QMessageBox::critical(m_qnetTool,"Error",message);
1003  return;
1004  }
1005  }
1006 
1007  try {
1008  // Read apriori surface point if it exists so that point is
1009  // replaced, but sigmas are retained. Save sigmas because the
1010  // SurfacePoint class will change them if the coordinates change.
1011  if (m_editPoint->HasAprioriCoordinates()) {
1012  SurfacePoint aprioriPt = m_editPoint->GetAprioriSurfacePoint();
1013  Distance latSigma = aprioriPt.GetLatSigmaDistance();
1014  Distance lonSigma = aprioriPt.GetLonSigmaDistance();
1015  Distance radiusSigma = aprioriPt.GetLocalRadiusSigma();
1016  aprioriPt.SetSphericalCoordinates(Latitude(lat, Angle::Degrees),
1017  Longitude(lon, Angle::Degrees),
1018  Distance(radius, Distance::Meters));
1019  aprioriPt.SetSphericalSigmasDistance(latSigma, lonSigma, radiusSigma);
1020  m_editPoint->SetAprioriSurfacePoint(aprioriPt);
1021  }
1022  else {
1023  m_editPoint->SetAprioriSurfacePoint(SurfacePoint(
1024  Latitude(lat, Angle::Degrees),
1025  Longitude(lon, Angle::Degrees),
1026  Distance(radius, Distance::Meters)));
1027  }
1028  }
1029  catch (IException &e) {
1030  QString message = "Unable to set Apriori Surface Point.\n";
1031  message += "Latitude = " + QString::number(lat);
1032  message += " Longitude = " + QString::number(lon);
1033  message += " Radius = " + QString::number(radius) + "\n";
1034  message += e.toString();
1035  QMessageBox::critical(m_qnetTool,"Error",message);
1036  }
1037  m_editPoint->SetAprioriSurfacePointSource(m_groundSurfacePointSource);
1038  m_editPoint->SetAprioriSurfacePointSourceFile(m_groundSourceFile);
1039 
1041 
1042  }
1043 
1044 
1045 
1061 
1062  // Make a copy of edit point for updating the control net since the edit
1063  // point is still loaded in the point editor.
1064  ControlPoint *updatePoint = new ControlPoint;
1065  *updatePoint = *m_editPoint;
1066 
1067  // If this is a fixed or constrained point, see if there is a temporary
1068  // measure holding the coordinate information from the ground source.
1069  // If so, delete this measure before saving point. Clear out the
1070  // fixed Measure variable (memory deleted in ControlPoint::Delete).
1071  if (updatePoint->GetType() != ControlPoint::Free &&
1072  updatePoint->HasSerialNumber(m_groundSN)) {
1073  updatePoint->Delete(m_groundSN);
1074  }
1075 
1076  // If edit point exists in the network, save the updated point. If it
1077  // does not exist, add it.
1078  if (m_controlNet->ContainsPoint(updatePoint->GetId())) {
1079  ControlPoint *p;
1080  p = m_controlNet->GetPoint(QString(updatePoint->GetId()));
1081  *p = *updatePoint;
1082  delete updatePoint;
1083  updatePoint = NULL;
1084  }
1085  else {
1086  m_controlNet->AddPoint(updatePoint);
1087  }
1088 
1089  // Change Save Measure button text back to default
1090  m_savePoint->setPalette(m_saveDefaultPalette);
1091 
1092  // ???? Why was this here??? loadPoint();
1093  // emit signal so the nav tool refreshes the list
1094  emit refreshNavList();
1095  // emit signal so the nav tool can update edit point
1096  emit editPointChanged(m_editPoint->GetId());
1097  // emit a signal to alert user to save when exiting
1098  emit netChanged();
1099  // Refresh chipViewports to show new positions of controlPoints
1100  m_pointEditor->refreshChips();
1101  }
1102 
1103 
1104 
1119  void QnetTool::setPointType (int pointType) {
1120  if (m_editPoint == NULL) return;
1121 
1122  // If pointType is equal to current type, nothing to do
1123  if (m_editPoint->GetType() == pointType) return;
1124 
1125  if (pointType != ControlPoint::Free && m_leftMeasure->IsIgnored()) {
1126  m_pointType->setCurrentIndex((int) m_editPoint->GetType());
1127  QString message = "The reference measure is Ignored. Unset the Ignore flag on the ";
1128  message += "reference measure before setting the point type to Constrained or Fixed.";
1129  QMessageBox::warning(m_qnetTool, "Ignored Reference Measure", message);
1130  return;
1131  }
1132 
1133  bool unloadGround = false;
1134  if (m_editPoint->GetType() != ControlPoint::Free && pointType == ControlPoint::Free)
1135  unloadGround = true;
1136 
1137  // save the old point's type
1138  int temp = m_editPoint->GetType();
1139 
1140  ControlPoint::Status status = m_editPoint->SetType((ControlPoint::PointType) pointType);
1141  if (status == ControlPoint::PointLocked) {
1142  m_pointType->setCurrentIndex((int) m_editPoint->GetType());
1143  QString message = "This control point is edit locked. The point type cannot be changed. You ";
1144  message += "must first unlock the point by clicking the check box above labeled ";
1145  message += "\"Edit Lock Point\".";
1146  QMessageBox::warning(m_qnetTool, "Point Locked", message);
1147  return;
1148  }
1149 
1150  // If ground loaded and changing from Free to ground point,
1151  // read temporary ground measure to the point
1152  // Note: changing between Fixed and Constrained will not reload the ground measure
1153  if (pointType != ControlPoint::Free && temp == ControlPoint::Free && m_groundOpen) {
1155  m_pointEditor->colorizeSaveButton();
1156  }
1157  // If going from constrained or fixed to free, unload the ground measure.
1158  else if (unloadGround) {
1159  // Find in point and delete, it will be re-created with current
1160  // ground source if this is a fixed point
1161  if (m_editPoint->HasSerialNumber(m_groundSN)) {
1162  m_editPoint->Delete(m_groundSN);
1163  }
1164 
1165  loadPoint();
1166  m_pointEditor->colorizeSaveButton();
1167  }
1168 
1170  }
1171 
1172 
1173 
1186 
1187  if (!m_groundOpen) return;
1188 
1189  if (findPointLocation()) {
1190  ControlMeasure *groundMeasure = createTemporaryGroundMeasure();
1191 
1192  // Add to measure combo boxes
1193  QString file = m_serialNumberList->fileName(groundMeasure->GetCubeSerialNumber());
1194  m_pointFiles<<file;
1195  QString tempFileName = FileName(file).name();
1196 
1197  m_leftCombo->addItem(tempFileName);
1198  m_rightCombo->addItem(tempFileName);
1199  int rightIndex = m_rightCombo->findText((QString)m_groundFile);
1200  m_rightCombo->setCurrentIndex(rightIndex);
1201  selectRightMeasure(rightIndex);
1202 
1204 
1205  loadMeasureTable();
1206  }
1207  }
1208 
1209 
1210 
1220  void QnetTool::setLockPoint (bool lock) {
1221  if (m_editPoint == NULL) return;
1222 
1223  m_editPoint->SetEditLock(lock);
1225  }
1226 
1227 
1228 
1239  void QnetTool::setIgnorePoint (bool ignore) {
1240  if (m_editPoint == NULL) return;
1241 
1242  ControlPoint::Status status = m_editPoint->SetIgnored(ignore);
1243  if (status == ControlPoint::PointLocked) {
1244  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1245  QString message = "This control point is edit locked. The Ignored status cannot be ";
1246  message += "changed. You must first unlock the point by clicking the check box above ";
1247  message += "labeled \"Edit Lock Point\".";
1248  QMessageBox::warning(m_qnetTool, "Point Locked", message);
1249  return;
1250  }
1252  }
1253 
1254 
1255 
1256 
1272  void QnetTool::setLockLeftMeasure (bool lock) {
1273 
1274  if (m_editPoint->IsEditLocked()) {
1275  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1276  QMessageBox::warning(m_qnetTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1277  " before changing a measure.");
1278  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1279  return;
1280  }
1281 
1282  if (m_leftMeasure != NULL) m_leftMeasure->SetEditLock(lock);
1283 
1284  // If the right chip is the same as the left chip , update the right editLock
1285  // box.
1286  if (m_rightMeasure != NULL) {
1287  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1288  m_rightMeasure->SetEditLock(lock);
1289  m_lockRightMeasure->setChecked(lock);
1290  }
1291  }
1292  emit measureChanged();
1293  }
1294 
1295 
1313  void QnetTool::setIgnoreLeftMeasure (bool ignore) {
1314  if (m_leftMeasure != NULL) m_leftMeasure->SetIgnored(ignore);
1315 
1316  // If the right chip is the same as the left chip , update the right
1317  // ignore box.
1318  if (m_rightMeasure != NULL) {
1319  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1320  m_rightMeasure->SetIgnored(ignore);
1321  m_ignoreRightMeasure->setChecked(ignore);
1322  }
1323  }
1324  emit measureChanged();
1325  }
1326 
1327 
1344 
1345  if (m_editPoint->IsEditLocked()) {
1346  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1347  QMessageBox::warning(m_qnetTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1348  " before changing a measure.");
1349  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1350  return;
1351  }
1352 
1353  if (m_rightMeasure != NULL) m_rightMeasure->SetEditLock(lock);
1354 
1355  // If the left chip is the same as the right chip , update the left editLock box.
1356  if (m_leftMeasure != NULL) {
1357  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
1358  m_leftMeasure->SetEditLock(lock);
1359  m_lockLeftMeasure->setChecked(lock);
1360  }
1361  }
1362  emit measureChanged();
1363  }
1364 
1365 
1383  void QnetTool::setIgnoreRightMeasure (bool ignore) {
1384  if (m_rightMeasure != NULL) m_rightMeasure->SetIgnored(ignore);
1385 
1386  // If the right chip is the same as the left chip , update the right
1387  // ignore blox.
1388  if (m_leftMeasure != NULL) {
1389  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1390  m_leftMeasure->SetIgnored(ignore);
1391  m_ignoreLeftMeasure->setChecked(ignore);
1392  }
1393  }
1394  emit measureChanged();
1395  }
1396 
1397 
1398 
1405  if (m_cnetFileName.isEmpty()) {
1406  QString message = "This is a new network, you must select "
1407  "\"Save As\" under the File Menu.";
1408  QMessageBox::critical(m_qnetTool, "Error", message);
1409  return;
1410  }
1411  emit qnetToolSave();
1412  //m_controlNet->Write(m_cnetFileName);
1413  }
1414 
1415 
1416 
1421  emit qnetToolSaveAs();
1422  }
1423 
1424 
1425 
1426 
1430  void QnetTool::updateList() {
1431 
1432  //m_pointEditor->setSerialList (*m_serialNumberList);
1433 
1434  }
1435 
1436 
1453  void QnetTool::updateNet(QString cNetFileName) {
1454  m_cnetFileName = cNetFileName;
1455  m_qnetTool->setWindowTitle("Qnet Tool - Control Network File: " +
1456  cNetFileName);
1457  //m_pointEditor->setControlNet(*m_controlNet);
1458 
1459  }
1460 
1461 
1462 
1475  QAction *action = new QAction(pad);
1476  action->setIcon(QPixmap(toolIconDir()+"/stock_draw-connector-with-arrows.png"));
1477  action->setToolTip("Control Point Editor (T)");
1478  action->setShortcut(Qt::Key_T);
1479  QObject::connect(action,SIGNAL(triggered(bool)),this,SLOT(showNavWindow(bool)));
1480  return action;
1481  }
1482 
1483 
1484 
1519  void QnetTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
1520  MdiCubeViewport *cvp = cubeViewport();
1521  if (cvp == NULL) return;
1522 
1523  QString file = cvp->cube()->fileName();
1524  QString sn;
1525  try {
1526  sn = m_serialNumberList->serialNumber(file);
1527  }
1528  catch (IException &e) {
1529  QString message = "Cannot get serial number for " + file + ". Is file contained in the ";
1530  message += "cube list?\n";
1531  message += e.toString();
1532  QMessageBox::critical(m_qnetTool, "Error", message);
1533  return;
1534  }
1535 
1536  double samp,line;
1537  cvp->viewportToCube(p.x(),p.y(),samp,line);
1538 
1539  m_leftFile.clear();
1540 
1541  if (s == Qt::LeftButton) {
1542  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1543  QString message = "No points exist for editing. Create points ";
1544  message += "using the right mouse button.";
1545  QMessageBox::warning(m_qnetTool, "Warning", message);
1546  return;
1547  }
1548 
1549  if (sn == m_groundSN) {
1550  QString message = "Cannot select point for editing on ground source. Select ";
1551  message += "point using un-projected images or the Navigator Window.";
1552  QMessageBox::critical(m_qnetTool, "Error", message);
1553  return;
1554  }
1555 
1556  // Find closest control point in network
1557  QString sn = m_serialNumberList->serialNumber(file);
1558 
1559  // since we are in a connected slot, we need to handle exceptions thrown by FindClosest
1560  try {
1561  ControlPoint *point = m_controlNet->FindClosest(sn, samp, line);
1562  modifyPoint(point);
1563  }
1564  catch (IException &ie) {
1565  QString message = "No points exist for editing. Create points using the right mouse";
1566  message += " button.";
1567  QMessageBox::warning(m_qnetTool, "Warning", message);
1568  return;
1569  }
1570  }
1571 
1572  else if (s == Qt::MidButton) {
1573  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1574  QString message = "No points exist for deleting. Create points ";
1575  message += "using the right mouse button.";
1576  QMessageBox::warning(m_qnetTool, "Warning", message);
1577  return;
1578  }
1579 
1580  if (m_groundOpen && file == m_groundCube->fileName()) {
1581  QString message = "Cannot select point for deleting on ground source. Select ";
1582  message += "point using un-projected images or the Navigator Window.";
1583  QMessageBox::critical(m_qnetTool, "Error", message);
1584  return;
1585  }
1586  // Find closest control point in network
1587  ControlPoint *point = NULL;
1588  try {
1589  point = m_controlNet->FindClosest(sn, samp, line);
1590 
1591  if (point == NULL) {
1592  QString message = "No points exist for deleting. Create points ";
1593  message += "using the right mouse button.";
1594  QMessageBox::warning(m_qnetTool, "Warning", message);
1595  return;
1596  }
1597  }
1598  catch (IException &e) {
1599  QString message = "Cannot find point on this image for deleting.";
1600  QMessageBox::critical(m_qnetTool, "Error", message);
1601  return;
1602  }
1603 
1604  deletePoint(point);
1605  }
1606  else if (s == Qt::RightButton) {
1607  m_leftFile = file;
1608  UniversalGroundMap *gmap = cvp->universalGroundMap();
1609  if (!gmap->SetImage(samp,line)) {
1610  QString message = "Invalid latitude or longitude at this point. ";
1611  QMessageBox::critical(m_qnetTool,"Error", message);
1612  return;
1613  }
1614  double lat = gmap->UniversalLatitude();
1615  double lon = gmap->UniversalLongitude();
1616  if (m_groundOpen && file == m_groundCube->fileName()) {
1617  createFixedPoint (lat,lon);
1618  }
1619  else {
1620  createPoint(lat,lon);
1621  }
1622  }
1623  }
1624 
1625 
1626 
1671  void QnetTool::createPoint(double lat,double lon) {
1672 
1673  // TODO: ADD AUTOSEED OPTION (CHECKBOX?)
1674 
1675  // Create list box of all files highlighting those that
1676  // contain the point.
1677  QStringList pointFiles;
1678 
1679  Camera *cam;
1680  for(int i = 0; i < m_serialNumberList->size(); i++) {
1681  if (m_serialNumberList->serialNumber(i) == m_groundSN) continue;
1682  cam = m_controlNet->Camera(i);
1683  if(cam->SetUniversalGround(lat, lon)) {
1684  // Make sure point is within image boundary
1685  double samp = cam->Sample();
1686  double line = cam->Line();
1687  if (samp >= 1 && samp <= cam->Samples() &&
1688  line >= 1 && line <= cam->Lines()) {
1689  pointFiles<<m_serialNumberList->fileName(i);
1690  }
1691  }
1692  }
1693 
1694  NewControlPointDialog *newPointDialog =
1695  new NewControlPointDialog(m_controlNet, m_serialNumberList, m_lastUsedPointId);
1696  newPointDialog->setFiles(pointFiles);
1697  if (newPointDialog->exec()) {
1698  m_lastUsedPointId = newPointDialog->pointId();
1699  ControlPoint *newPoint =
1700  new ControlPoint(m_lastUsedPointId);
1701 
1702  // If this ControlPointId already exists, message box pops up and user is
1703  // asked to enter a new value.
1704  if (m_controlNet->ContainsPoint(newPoint->GetId())) {
1705  QString message = "A ControlPoint with Point Id = [" + newPoint->GetId();
1706  message += "] already exists. Re-enter Point Id for this ControlPoint.";
1707  QMessageBox::warning(m_qnetTool, "New Point Id", message);
1708  pointFiles.clear();
1709  delete newPoint;
1710  newPoint = NULL;
1711  createPoint(lat, lon);
1712  return;
1713  }
1714 
1716 
1717  QStringList selectedFiles = newPointDialog->selectedFiles();
1718  foreach (QString selectedFile, selectedFiles) {
1719  // Create measure for any file selected
1720  ControlMeasure *m = new ControlMeasure;
1721  // Find serial number for this file
1722  QString sn =
1723  m_serialNumberList->serialNumber(selectedFile);
1724  m->SetCubeSerialNumber(sn);
1725  int camIndex =
1726  m_serialNumberList->fileNameIndex(selectedFile);
1727  cam = m_controlNet->Camera(camIndex);
1728  cam->SetUniversalGround(lat,lon);
1729  m->SetCoordinate(cam->Sample(),cam->Line());
1730  m->SetAprioriSample(cam->Sample());
1731  m->SetAprioriLine(cam->Line());
1734  m->SetCamera(cam);
1735  newPoint->Add(m);
1736  }
1737  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1738  delete m_editPoint;
1739  m_editPoint = NULL;
1740  }
1741  m_editPoint = newPoint;
1742 
1743  // If the image that the user clicked on to select the point is not
1744  // included, clear out the leftFile value.
1745  if (!m_leftFile.isEmpty()) {
1746  if (selectedFiles.indexOf(m_leftFile) == -1) {
1747  m_leftFile.clear();
1748  }
1749  }
1750 
1751  // Load new point in QnetTool
1752  loadPoint();
1753  m_qnetTool->setVisible(true);
1754  m_qnetTool->raise();
1755 
1757  m_pointEditor->templateFileName());
1758 
1759 
1760  // emit signal so the nave tool refreshes the list
1761  emit refreshNavList();
1762  // emit signal so the nav tool can update edit point
1763  emit editPointChanged(m_editPoint->GetId());
1765  delete newPointDialog;
1766 
1767  }
1768  }
1769 
1770 
1771 
1772 
1773 
1774 
1786  void QnetTool::createFixedPoint(double lat,double lon) {
1787 
1788  // TODO: ADD AUTOSEED OPTION (CHECKBOX?)
1789 
1790  // Create list of list box of all files highlighting those that
1791  // contain the point.
1792  QStringList pointFiles;
1793 
1794  Camera *cam;
1795  for (int i=0; i<m_serialNumberList->size(); i++) {
1796  if (m_serialNumberList->serialNumber(i) == m_groundSN) continue;
1797  cam = m_controlNet->Camera(i);
1798  if (cam->SetUniversalGround(lat,lon)) {
1799  // Make sure point is within image boundary
1800  double samp = cam->Sample();
1801  double line = cam->Line();
1802  if (samp >= 1 && samp <= cam->Samples() &&
1803  line >= 1 && line <= cam->Lines()) {
1804  pointFiles<<m_serialNumberList->fileName(i);
1805  }
1806  }
1807  }
1808 
1809  if (pointFiles.count() == 0) {
1810  QString message = "Point does not intersect any images.";
1811  QMessageBox::critical(m_qnetTool, "No intersection", message);
1812  return;
1813  }
1814 
1815  QnetFixedPointDialog *fixedPointDialog = new QnetFixedPointDialog(this, m_lastUsedPointId);
1816  fixedPointDialog->setFiles(pointFiles);
1817  if (fixedPointDialog->exec()) {
1818  ControlPoint *fixedPoint =
1819  new ControlPoint(fixedPointDialog->pointId());
1820 
1821  if (fixedPointDialog->isFixed()) {
1822  fixedPoint->SetType(ControlPoint::Fixed);
1823  }
1824  else {
1825  fixedPoint->SetType(ControlPoint::Constrained);
1826  }
1827 
1828  // If this ControlPointId already exists, message box pops up and user is
1829  // asked to enter a new value.
1830  if (m_controlNet->ContainsPoint(fixedPoint->GetId())) {
1831  QString message = "A ControlPoint with Point Id = [" + fixedPoint->GetId();
1832  message += "] already exists. Re-enter Point Id for this ControlPoint.";
1833  QMessageBox::warning(m_qnetTool, "New Point Id", message);
1834  pointFiles.clear();
1835  delete fixedPoint;
1836  fixedPoint = NULL;
1837  createFixedPoint(lat,lon);
1838  return;
1839  }
1840 
1841  fixedPoint->SetChooserName(Application::UserName());
1842 
1843  QStringList selectedFiles = fixedPointDialog->selectedFiles();
1844  foreach (QString selectedFile, selectedFiles) {
1845  // Create measure for any file selected
1846  ControlMeasure *m = new ControlMeasure;
1847  // Find serial number for this file
1848  QString sn =
1849  m_serialNumberList->serialNumber(selectedFile);
1850 
1851  // If ground, do not add measure, it will be added in loadPoint
1852  if (sn == m_groundSN) continue;
1853 
1854  m->SetCubeSerialNumber(sn);
1855  int camIndex =
1856  m_serialNumberList->fileNameIndex(selectedFile);
1857  cam = m_controlNet->Camera(camIndex);
1858  cam->SetUniversalGround(lat,lon);
1859  m->SetCoordinate(cam->Sample(),cam->Line());
1862  m->SetCamera(cam);
1863  fixedPoint->Add(m);
1864  }
1865 
1866  // ?????? What radius , check for dem or shape model
1867  double radius = 0;
1868  if (m_demOpen) {
1869  radius = demRadius(lat,lon);
1870  if (radius == Null) {
1871  QString msg = "Could not read radius from DEM, will default to the "
1872  "local radius of the first measure in the control point. This "
1873  "will be updated to the local radius of the chosen reference "
1874  "measure.";
1875  QMessageBox::warning(m_qnetTool, "Warning", msg);
1876  if ((*fixedPoint)[0]->Camera()->SetGround(
1878  radius = (*fixedPoint)[0]->Camera()->LocalRadius().meters();
1879  }
1880  else {
1881  QString msg = "Error trying to get radius at this pt. "
1882  "Lat/Lon does not fall on the reference measure. "
1883  "Cannot create this point.";
1884  QMessageBox::critical(m_qnetTool, "Error", msg);
1885  delete fixedPoint;
1886  fixedPoint = NULL;
1887  delete fixedPointDialog;
1888  fixedPointDialog = NULL;
1889  return;
1890  }
1891  }
1892  }
1893  else {
1894  if ((*fixedPoint)[0]->Camera()->SetGround(
1896  radius = (*fixedPoint)[0]->Camera()->LocalRadius().meters();
1897  }
1898  else {
1899  QString msg = "Error trying to get radius at this pt. "
1900  "Lat/Lon does not fall on the reference measure. "
1901  "Cannot create this point.";
1902  QMessageBox::critical(m_qnetTool, "Error", msg);
1903  delete fixedPoint;
1904  fixedPoint = NULL;
1905  delete fixedPointDialog;
1906  fixedPointDialog = NULL;
1907  return;
1908  }
1909  }
1910 
1912  Latitude(lat, Angle::Degrees),
1913  Longitude(lon, Angle::Degrees),
1914  Distance(radius, Distance::Meters)));
1915 
1916  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1917  delete m_editPoint;
1918  m_editPoint = NULL;
1919  }
1920  m_editPoint = fixedPoint;
1921 
1922  // Load new point in QnetTool
1923  loadPoint();
1924  m_qnetTool->setVisible(true);
1925  m_qnetTool->raise();
1926 
1927  delete fixedPointDialog;
1928  fixedPointDialog = NULL;
1929 
1930  // emit signal so the nave tool refreshes the list
1931  emit refreshNavList();
1932  // emit signal so the nav tool can update edit point
1933  emit editPointChanged(m_editPoint->GetId());
1935  }
1936  }
1937 
1938 
1939 
1961 
1962  // Make a copy and make sure editPoint is a copy (which means it does not
1963  // have a parent network.
1964  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1965  delete m_editPoint;
1966  m_editPoint = NULL;
1967  }
1968  m_editPoint = new ControlPoint;
1969  *m_editPoint = *point;
1970  loadPoint();
1971 
1972  // Change point in viewport to red so user can see what point they are
1973  // about to delete.
1974  // the nav tool will update edit point
1975  emit editPointChanged(m_editPoint->GetId());
1976 
1977  QnetDeletePointDialog *deletePointDialog = new QnetDeletePointDialog;
1978  QString CPId = m_editPoint->GetId();
1979  deletePointDialog->pointIdValue->setText(CPId);
1980 
1981  // Need all files for this point
1982  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1983  ControlMeasure &m = *(*m_editPoint)[i];
1984  QString file = m_serialNumberList->fileName(m.GetCubeSerialNumber());
1985  deletePointDialog->fileList->addItem(file);
1986  }
1987 
1988  if (deletePointDialog->exec()) {
1989 
1990  int numDeleted = deletePointDialog->fileList->selectedItems().count();
1991 
1992  // Delete entire control point, either through deleteAllCheckBox or all measures selected
1993  if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1994  numDeleted == m_editPoint->GetNumMeasures()) {
1995 
1996  // If all measures being deleted, let user know and give them the option to quit operation
1997  if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1998  QString message = "You have selected all measures in this point to be deleted. This "
1999  "control point will be deleted. Do you want to delete this control point?";
2000  int response = QMessageBox::question(m_qnetTool,
2001  "Delete control point", message,
2002  QMessageBox::Yes | QMessageBox::No,
2003  QMessageBox::Yes);
2004  // If No, do nothing
2005  if (response == QMessageBox::No) {
2006  return;
2007  }
2008  }
2009 
2010  // First get rid of deleted point from m_filteredPoints list
2011  // need index in control net for pt
2012  //int i = m_controlNet->
2013  //m_filteredPoints.
2014  m_qnetTool->setVisible(false);
2015  // remove this point from the control network
2016  if (m_controlNet->DeletePoint(m_editPoint->GetId()) ==
2018  QMessageBox::information(m_qnetTool, "EditLocked Point",
2019  "This point is EditLocked and cannot be deleted.");
2020  return;
2021  }
2022  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
2023  delete m_editPoint;
2024  m_editPoint = NULL;
2025  }
2026  // emit signal so the nav tool refreshes the list
2027  emit refreshNavList();
2028  }
2029 
2030  // Delete specific measures from control point
2031  else {
2032  // Keep track of editLocked measures for reporting
2033  int lockedMeasures = 0;
2034  for (int i=0; i<deletePointDialog->fileList->count(); i++) {
2035  QListWidgetItem *item = deletePointDialog->fileList->item(i);
2036  if (!deletePointDialog->fileList->isItemSelected(item)) continue;
2037 
2038  // Do not delete reference without asking user
2039  if (m_editPoint->IsReferenceExplicit() &&
2040  (m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
2041  (*m_editPoint)[i]->GetCubeSerialNumber())) {
2042  QString message = "You are trying to delete the Reference measure."
2043  " Do you really want to delete the Reference measure?";
2044  switch (QMessageBox::question(m_qnetTool,
2045  "Delete Reference measure?", message,
2046  "&Yes", "&No", 0, 0)) {
2047  // Yes: skip to end of switch todelete the measure
2048  case 0:
2049  break;
2050  // No: continue to next measure in the loop
2051  case 1:
2052  // if only a single measure and it's reference and user chooses not to delete,
2053  // simply return. The point has not changed.
2054  if (numDeleted == 1) {
2055  return;
2056  }
2057  continue;
2058  }
2059  }
2060 
2061  if (m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
2062  lockedMeasures++;
2063  }
2064  }
2065 
2066  if (lockedMeasures > 0) {
2067  QMessageBox::information(m_qnetTool,"EditLocked Measures",
2068  QString::number(lockedMeasures) + " / "
2069  + QString::number(
2070  deletePointDialog->fileList->selectedItems().size()) +
2071  " measures are EditLocked and were not deleted.");
2072  }
2073 
2074  loadPoint();
2075  m_qnetTool->setVisible(true);
2076  m_qnetTool->raise();
2077 
2078  loadTemplateFile(m_pointEditor->templateFileName());
2079  }
2080 
2081  // emit a signal to alert user to save when exiting
2082  emit netChanged();
2083 
2084  // emit signal so the nav tool can update edit point
2085  if (m_editPoint != NULL) {
2086  emit editPointChanged(m_editPoint->GetId());
2087  // Change Save Point button text to red
2089  }
2090  else {
2091  // if the entire point is deleted, update with point Id = ""
2092  // this signal is connected to QnetTool::paintAllViewports
2093  // and QnetNavTool::updateEditPoint
2094  emit editPointChanged("");
2095  }
2096  }
2097  }
2098 
2099 
2100 
2110 
2111  // If no measures, print info and return
2112  if (point->GetNumMeasures() == 0) {
2113  QString message = "This point has no measures.";
2114  QMessageBox::warning(m_qnetTool, "Warning", message);
2115  // update nav list to re-highlight old point
2116  if (m_editPoint != NULL) {
2117  // emit signal so the nav tool can update edit point
2118  emit editPointChanged(m_editPoint->GetId());
2119  }
2120  else {
2121  // this signal is connected to QnetTool::paintAllViewports
2122  // and QnetNavTool::updateEditPoint
2123  emit editPointChanged("");
2124  }
2125  return;
2126  }
2127  // Make a copy of point for editing, first make sure memory not already
2128  // allocated
2129  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
2130  delete m_editPoint;
2131  m_editPoint = NULL;
2132  }
2133  m_editPoint = new ControlPoint;
2134  *m_editPoint = *point;
2135 
2136  // If navTool modfify button pressed, m_leftFile needs to be reset
2137  // TODO: better way - have 2 slots
2138  if (sender() != this) m_leftFile.clear();
2139  loadPoint();
2140  m_qnetTool->setVisible(true);
2141  m_qnetTool->raise();
2142  loadTemplateFile(m_pointEditor->templateFileName());
2143 
2144  // emit signal so the nav tool can update edit point
2145  emit editPointChanged(m_editPoint->GetId());
2146 
2147  // New point loaded, make sure Save Measure Button text is default
2148  m_savePoint->setPalette(m_saveDefaultPalette);
2149  }
2150 
2151 
2162  bool located = true;
2163 
2164  // Use apriori surface point to find location on ground source. If
2165  // apriori surface point does not exist use reference measure
2166  double lat = 0.;
2167  double lon = 0.;
2168  if (m_editPoint->HasAprioriCoordinates()) {
2169  SurfacePoint sPt = m_editPoint->GetAprioriSurfacePoint();
2170  lat = sPt.GetLatitude().degrees();
2171  lon = sPt.GetLongitude().degrees();
2172  }
2173  else {
2174  ControlMeasure m = *(m_editPoint->GetRefMeasure());
2175  int camIndex = m_serialNumberList->serialNumberIndex(m.GetCubeSerialNumber());
2176  Camera *cam;
2177  cam = m_controlNet->Camera(camIndex);
2178  cam->SetImage(m.GetSample(),m.GetLine());
2179  lat = cam->UniversalLatitude();
2180  lon = cam->UniversalLongitude();
2181  }
2182 
2183  // Try to locate point position on current ground source,
2184  // TODO ???if doesn't exist,???
2185  if (!m_groundGmap->SetUniversalGround(lat,lon)) {
2186  located = false;
2187  QString message = "This point does not exist on the ground source.\n";
2188  message += "Latitude = " + QString::number(lat);
2189  message += " Longitude = " + QString::number(lon);
2190  message += "\n A ground measure will not be created.";
2191  QMessageBox::warning(m_qnetTool, "Warning", message);
2192  }
2193 
2194  return located;
2195  }
2196 
2197 
2208 
2209  // This measure will be deleted when the ControlPoint is saved to the
2210  // ControlNet.
2211  ControlMeasure *groundMeasure = new ControlMeasure;
2212  groundMeasure->SetCubeSerialNumber(m_groundSN);
2213  groundMeasure->SetType(ControlMeasure::Candidate);
2214  groundMeasure->SetCoordinate(m_groundGmap->Sample(),m_groundGmap->Line());
2215  m_editPoint->Add(groundMeasure);
2216 
2217  return groundMeasure;
2218  }
2219 
2220 
2245 
2246  // Write pointId
2247  QString CPId = m_editPoint->GetId();
2248  QString ptId("Point ID: ");
2249  ptId += (QString) CPId;
2250  m_ptIdValue->setText(ptId);
2251 
2252  // Write point type
2253 // QString ptType("Point Type: ");
2254 // ptType += (QString) m_editPoint->GetPointTypeString();
2255 // m_pointType->setText(ptType);
2256  m_pointType->setCurrentIndex((int) m_editPoint->GetType());
2257 
2258  // Write number of measures
2259  QString ptsize = "Number of Measures: " +
2260  QString::number(m_editPoint->GetNumMeasures());
2261  m_numMeasures->setText(ptsize);
2262 
2263  // Set EditLock box correctly
2264  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
2265 
2266  // Set ignore box correctly
2267  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
2268 
2269  // Clear combo boxes
2270  m_leftCombo->clear();
2271  m_rightCombo->clear();
2272  m_pointFiles.clear();
2273 
2274  // Find in point and delete, it will be re-created with current
2275  // ground source if this is a fixed point
2276  if (m_editPoint->HasSerialNumber(m_groundSN)) {
2277  m_editPoint->Delete(m_groundSN);
2278  }
2279 
2280  // If fixed, add ground source file to combos, create a measure for
2281  // the ground source, load reference on left, ground source on right
2282  if (m_groundOpen && (m_editPoint->GetType() != ControlPoint::Free)) {
2283 
2284  if (findPointLocation()) {
2285  // Create a temporary measure to hold the ground point info for ground source
2286  // This measure will be deleted when the ControlPoint is saved to the
2287  // ControlNet.
2288  // TODO: Does open ground source match point ground source
2290  }
2291  }
2292 
2293  // Load a radius source if there isn't a radius source already open, and there is a ground source
2294  if (m_groundOpen && !m_demOpen) {
2296  }
2297 
2298 
2299  // Need all files for this point
2300  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
2301  ControlMeasure &m = *(*m_editPoint)[i];
2302  QString file = m_serialNumberList->fileName(m.GetCubeSerialNumber());
2303  m_pointFiles<<file;
2304  QString tempFileName = FileName(file).name();
2305  m_leftCombo->addItem(tempFileName);
2306  m_rightCombo->addItem(tempFileName);
2307  if (m_editPoint->IsReferenceExplicit() &&
2308  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
2309  m_leftCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2310  m_rightCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2311  }
2312  }
2313 
2314 
2315  // TODO: WHAT HAPPENS IF THERE IS ONLY ONE MEASURE IN THIS CONTROLPOINT??
2316  // Assuming combo loaded in same order as measures in the control point-is
2317  // this a safe assumption???
2318  //
2319  // Find the file from the cubeViewport that was originally used to select
2320  // the point, this will be displayed on the left ChipViewport, unless the
2321  // point was selected on the ground source image. In this case, simply
2322  // load the first measure on the left.
2323  int leftIndex = 0;
2324  int rightIndex = 0;
2325  // Check for reference
2326  if (m_editPoint->IsReferenceExplicit()) {
2327  leftIndex = m_editPoint->IndexOfRefMeasure();
2328  }
2329  else {
2330  if ((m_editPoint->GetType() == ControlPoint::Free) && !m_leftFile.isEmpty()) {
2331  QString baseFileName = FileName(m_leftFile).name();
2332  leftIndex = m_leftCombo->findText(baseFileName);
2333  // Sanity check
2334  if (leftIndex < 0 ) leftIndex = 0;
2335  }
2336  }
2337 
2338  // Determine index for right measure.
2339  // First, try to find correct ground. If no correct ground, set right index to either 0 or 1,
2340  // depending on value of the left index.
2341  if (m_groundOpen && (m_editPoint->GetType() != ControlPoint::Free)) {
2342  rightIndex = m_rightCombo->findText((QString)m_groundFile);
2343  }
2344  if (rightIndex <= 0) {
2345  if (leftIndex == 0) {
2346  rightIndex = 1;
2347  }
2348  else {
2349  rightIndex = 0;
2350  }
2351  }
2352 
2353  // Handle pts with a single measure, for now simply put measure on left/right
2354  // Evenutally put on left with black on right??
2355  if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0;
2356  m_rightCombo->setCurrentIndex(rightIndex);
2357  m_leftCombo->setCurrentIndex(leftIndex);
2358  // Initialize pointEditor with measures
2359  selectLeftMeasure(leftIndex);
2360  selectRightMeasure(rightIndex);
2361 
2363 
2364  loadMeasureTable();
2365  }
2366 
2367 
2368 
2369 
2370 
2379  if (m_measureWindow == NULL) {
2380  m_measureWindow = new QMainWindow();
2381  m_measureTable = new QTableWidget();
2382  m_measureTable->setMinimumWidth(1600);
2383  m_measureTable->setAlternatingRowColors(true);
2384  m_measureWindow->setCentralWidget(m_measureTable);
2385  }
2386  else {
2387  m_measureTable->clear();
2388  m_measureTable->setSortingEnabled(false);
2389  }
2390  m_measureTable->setRowCount(m_editPoint->GetNumMeasures());
2391  m_measureTable->setColumnCount(NUMCOLUMNS);
2392 
2393  QStringList labels;
2394  for (int i=0; i<NUMCOLUMNS; i++) {
2395  labels<<measureColumnToString((MeasureColumns)i);
2396  }
2397  m_measureTable->setHorizontalHeaderLabels(labels);
2398 
2399  // Fill in values
2400  for (int row=0; row<m_editPoint->GetNumMeasures(); row++) {
2401  int column = 0;
2402  ControlMeasure &m = *(*m_editPoint)[row];
2403 
2404  QString file = m_serialNumberList->fileName(m.GetCubeSerialNumber());
2405  QTableWidgetItem *tableItem = new QTableWidgetItem(QString(file));
2406  m_measureTable->setItem(row,column++,tableItem);
2407 
2408  tableItem = new QTableWidgetItem(QString(m.GetCubeSerialNumber()));
2409  m_measureTable->setItem(row,column++,tableItem);
2410 
2411  tableItem = new QTableWidgetItem();
2412  tableItem->setData(0,m.GetSample());
2413  m_measureTable->setItem(row,column++,tableItem);
2414 
2415  tableItem = new QTableWidgetItem();
2416  tableItem->setData(0,m.GetLine());
2417  m_measureTable->setItem(row,column++,tableItem);
2418 
2419  if (m.GetAprioriSample() == Null) {
2420  tableItem = new QTableWidgetItem("Null");
2421  }
2422  else {
2423  tableItem = new QTableWidgetItem();
2424  tableItem->setData(0,m.GetAprioriSample());
2425  }
2426  m_measureTable->setItem(row,column++,tableItem);
2427 
2428  if (m.GetAprioriLine() == Null) {
2429  tableItem = new QTableWidgetItem("Null");
2430  }
2431  else {
2432  tableItem = new QTableWidgetItem();
2433  tableItem->setData(0,m.GetAprioriLine());
2434  }
2435  m_measureTable->setItem(row,column++,tableItem);
2436 
2437  if (m.GetSampleResidual() == Null) {
2438  tableItem = new QTableWidgetItem(QString("Null"));
2439  }
2440  else {
2441  tableItem = new QTableWidgetItem();
2442  tableItem->setData(0,m.GetSampleResidual());
2443  }
2444  m_measureTable->setItem(row,column++,tableItem);
2445 
2446  if (m.GetLineResidual() == Null) {
2447  tableItem = new QTableWidgetItem(QString("Null"));
2448  }
2449  else {
2450  tableItem = new QTableWidgetItem();
2451  tableItem->setData(0,m.GetLineResidual());
2452  }
2453  m_measureTable->setItem(row,column++,tableItem);
2454 
2455  if (m.GetResidualMagnitude() == Null) {
2456  tableItem = new QTableWidgetItem(QString("Null"));
2457  }
2458  else {
2459  tableItem = new QTableWidgetItem();
2460  tableItem->setData(0,m.GetResidualMagnitude());
2461  }
2462  m_measureTable->setItem(row,column++,tableItem);
2463 
2464  double sampleShift = m.GetSampleShift();
2465  if (sampleShift == Null) {
2466  tableItem = new QTableWidgetItem(QString("Null"));
2467  }
2468  else {
2469  tableItem = new QTableWidgetItem();
2470  tableItem->setData(0,sampleShift);
2471  }
2472  m_measureTable->setItem(row,column++,tableItem);
2473 
2474  double lineShift = m.GetLineShift();
2475  if (lineShift == Null) {
2476  tableItem = new QTableWidgetItem(QString("Null"));
2477  }
2478  else {
2479  tableItem = new QTableWidgetItem();
2480  tableItem->setData(0,lineShift);
2481  }
2482  m_measureTable->setItem(row,column++,tableItem);
2483 
2484  double pixelShift = m.GetPixelShift();
2485  if (pixelShift == Null) {
2486  tableItem = new QTableWidgetItem(QString("Null"));
2487  }
2488  else {
2489  tableItem = new QTableWidgetItem();
2490  tableItem->setData(0,pixelShift);
2491  }
2492  m_measureTable->setItem(row,column++,tableItem);
2493 
2494  double goodnessOfFit = m.GetLogData(
2496  if (goodnessOfFit == Null) {
2497  tableItem = new QTableWidgetItem(QString("Null"));
2498  }
2499  else {
2500  tableItem = new QTableWidgetItem();
2501  tableItem->setData(0,goodnessOfFit);
2502  }
2503  m_measureTable->setItem(row,column++,tableItem);
2504 
2505  if (m.IsIgnored()) tableItem = new QTableWidgetItem("True");
2506  if (!m.IsIgnored()) tableItem = new QTableWidgetItem("False");
2507  m_measureTable->setItem(row,column++,tableItem);
2508 
2510  tableItem = new QTableWidgetItem("True");
2512  tableItem = new QTableWidgetItem("False");
2513  m_measureTable->setItem(row,column++,tableItem);
2514 
2515  tableItem = new QTableWidgetItem(
2517  m_measureTable->setItem(row,column,tableItem);
2518 
2519  // If reference measure set font on this row to bold
2520  if (m_editPoint->IsReferenceExplicit() &&
2521  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
2522  QFont font;
2523  font.setBold(true);
2524 
2525  for (int col=0; col<m_measureTable->columnCount(); col++)
2526  m_measureTable->item(row, col)->setFont(font);
2527  }
2528 
2529  }
2530 
2531  m_measureTable->resizeColumnsToContents();
2532  m_measureTable->resizeRowsToContents();
2533  m_measureTable->setSortingEnabled(true);
2534  m_measureWindow->show();
2535  }
2536 
2537 
2538 
2539  QString QnetTool::measureColumnToString(QnetTool::MeasureColumns column) {
2540  switch (column) {
2541  case FILENAME:
2542  return "FileName";
2543  case CUBESN:
2544  return "Serial #";
2545  case SAMPLE:
2546  return "Sample";
2547  case LINE:
2548  return "Line";
2549  case SAMPLERESIDUAL:
2550  return "Sample Residual";
2551  case LINERESIDUAL:
2552  return "Line Residual";
2553  case RESIDUALMAGNITUDE:
2554  return "Residual Magnitude";
2555  case SAMPLESHIFT:
2556  return "Sample Shift";
2557  case LINESHIFT:
2558  return "Line Shift";
2559  case PIXELSHIFT:
2560  return "Pixel Shift";
2561  case GOODNESSOFFIT:
2562  return "Goodness of Fit";
2563  case IGNORED:
2564  return "Ignored";
2565  case EDITLOCK:
2566  return "Edit Lock";
2567  case TYPE:
2568  return "Measure Type";
2569  case APRIORISAMPLE:
2570  return "Apriori Sample";
2571  case APRIORILINE:
2572  return "Apriori Line";
2573  }
2574  throw IException(IException::Programmer,
2575  "Invalid measure column passed to measureColumnToString", _FILEINFO_);
2576  }
2577 
2578 
2579  ControlNet *QnetTool::controlNet() {
2580  return m_controlNet;
2581  }
2582 
2583 
2584  const ControlNet *QnetTool::controlNet() const {
2585  return m_controlNet;
2586  }
2587 
2588 
2589  SerialNumberList *QnetTool::serialNumberList() {
2590  return m_serialNumberList;
2591  }
2592 
2593 
2594  const SerialNumberList *QnetTool::serialNumberList() const {
2595  return m_serialNumberList;
2596  }
2597 
2598 
2599  Workspace *QnetTool::workspace() const {
2600  return m_workspace;
2601  }
2602 
2603 
2616 
2617  QString s;
2618 
2619  SurfacePoint aprioriPoint = m_editPoint->GetAprioriSurfacePoint();
2620  if (aprioriPoint.GetLatitude().degrees() == Null) {
2621  s = "Apriori Latitude: Null";
2622  }
2623  else {
2624  s = "Apriori Latitude: " +
2625  QString::number(aprioriPoint.GetLatitude().degrees());
2626  }
2627  m_pointAprioriLatitude->setText(s);
2628  if (aprioriPoint.GetLongitude().degrees() == Null) {
2629  s = "Apriori Longitude: Null";
2630  }
2631  else {
2632  s = "Apriori Longitude: " +
2633  QString::number(aprioriPoint.GetLongitude().degrees());
2634  }
2635  m_pointAprioriLongitude->setText(s);
2636  if (aprioriPoint.GetLocalRadius().meters() == Null) {
2637  s = "Apriori Radius: Null";
2638  }
2639  else {
2640  s = "Apriori Radius: " +
2641  QString::number(aprioriPoint.GetLocalRadius().meters(),'f',2) +
2642  " <meters>";
2643  }
2644  m_pointAprioriRadius->setText(s);
2645 
2646  if (aprioriPoint.Valid()) {
2647  if (aprioriPoint.GetLatSigmaDistance().meters() == Null) {
2648  s = "Apriori Latitude Sigma: Null";
2649  }
2650  else {
2651  s = "Apriori Latitude Sigma: " +
2652  QString::number(aprioriPoint.GetLatSigmaDistance().meters()) +
2653  " <meters>";
2654  }
2655  m_pointAprioriLatitudeSigma->setText(s);
2656  if (aprioriPoint.GetLonSigmaDistance().meters() == Null) {
2657  s = "Apriori Longitude Sigma: Null";
2658  }
2659  else {
2660  s = "Apriori Longitude Sigma: " +
2661  QString::number(aprioriPoint.GetLonSigmaDistance().meters()) +
2662  " <meters>";
2663  }
2664  m_pointAprioriLongitudeSigma->setText(s);
2665  if (aprioriPoint.GetLocalRadiusSigma().meters() == Null) {
2666  s = "Apriori Radius Sigma: Null";
2667  }
2668  else {
2669  s = "Apriori Radius Sigma: " +
2670  QString::number(aprioriPoint.GetLocalRadiusSigma().meters()) +
2671  " <meters>";
2672  }
2673  m_pointAprioriRadiusSigma->setText(s);
2674  }
2675  else {
2676  s = "Apriori Latitude Sigma: Null";
2677  m_pointAprioriLatitudeSigma->setText(s);
2678  s = "Apriori Longitude Sigma: Null";
2679  m_pointAprioriLongitudeSigma->setText(s);
2680  s = "Apriori Radius Sigma: Null";
2681  m_pointAprioriRadiusSigma->setText(s);
2682  }
2683 
2684 
2685  SurfacePoint point = m_editPoint->GetAdjustedSurfacePoint();
2686  if (point.GetLatitude().degrees() == Null) {
2687  s = "Adjusted Latitude: Null";
2688  }
2689  else {
2690  s = "Adjusted Latitude: " + QString::number(point.GetLatitude().degrees());
2691  }
2692  m_pointLatitude->setText(s);
2693  if (point.GetLongitude().degrees() == Null) {
2694  s = "Adjusted Longitude: Null";
2695  }
2696  else {
2697  s = "Adjusted Longitude: " + QString::number(point.GetLongitude().degrees());
2698  }
2699  m_pointLongitude->setText(s);
2700  if (point.GetLocalRadius().meters() == Null) {
2701  s = "Adjusted Radius: Null";
2702  }
2703  else {
2704  s = "Adjusted Radius: " +
2705  QString::number(point.GetLocalRadius().meters(),'f',2) + " <meters>";
2706  }
2707  m_pointRadius->setText(s);
2708 
2709 
2710 
2711  }
2712 
2713 
2714 
2725  int curIndex = m_rightCombo->currentIndex();
2726  if (curIndex < m_rightCombo->count() - 1) {
2727  // update the right measure list index and select that measure
2728  m_rightCombo->setCurrentIndex(curIndex + 1);
2729  selectRightMeasure(curIndex+1);
2730  }
2731  }
2732 
2733 
2744  int curIndex = m_rightCombo->currentIndex();
2745  if (curIndex > 0) {
2746  // update the right measure list index and select that measure
2747  m_rightCombo->setCurrentIndex(curIndex - 1);
2748  selectRightMeasure(curIndex-1);
2749  }
2750  }
2751 
2752 
2753 
2766  QString file = m_pointFiles[index];
2767 
2768  QString serial = m_serialNumberList->serialNumber(file);
2769 
2770  // Make sure to clear out leftMeasure before making a copy of the selected
2771  // measure.
2772  if (m_leftMeasure != NULL) {
2773  delete m_leftMeasure;
2774  m_leftMeasure = NULL;
2775  }
2776  m_leftMeasure = new ControlMeasure();
2777  // Find measure for each file
2778  *m_leftMeasure = *((*m_editPoint)[serial]);
2779 
2780  // If m_leftCube is not null, delete before creating new one
2781  m_leftCube.reset(new Cube(file, "r"));
2782 
2783  // Update left measure of pointEditor
2784  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube.data(),
2785  m_editPoint->GetId());
2787 
2788  }
2789 
2790 
2801  QString file = m_pointFiles[index];
2802 
2803  QString serial = m_serialNumberList->serialNumber(file);
2804 
2805  // Make sure to clear out rightMeasure before making a copy of the selected
2806  // measure.
2807  if (m_rightMeasure != NULL) {
2808  delete m_rightMeasure;
2809  m_rightMeasure = NULL;
2810  }
2811  m_rightMeasure = new ControlMeasure();
2812  // Find measure for each file
2813  *m_rightMeasure = *((*m_editPoint)[serial]);
2814 
2815  // If m_rightCube is not null, delete before creating new one
2816  m_rightCube.reset(new Cube(file, "r"));
2817 
2818  // Update right measure of pointEditor
2819  m_pointEditor->setRightMeasure (m_rightMeasure, m_rightCube.data(),
2820  m_editPoint->GetId());
2822 
2823  }
2824 
2825 
2826 
2827 
2844 
2845  // Set editLock measure box correctly
2846  m_lockLeftMeasure->setChecked(IsMeasureLocked(
2847  m_leftMeasure->GetCubeSerialNumber()));
2848  // Set ignore measure box correctly
2849  m_ignoreLeftMeasure->setChecked(m_leftMeasure->IsIgnored());
2850 
2851  QString s = "Reference: ";
2852  if (m_editPoint->IsReferenceExplicit() &&
2853  (QString(m_leftMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2854  s += "True";
2855  }
2856  else {
2857  s += "False";
2858  }
2859  m_leftReference->setText(s);
2860 
2861  s = "Measure Type: ";
2862  if (m_leftMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2863  if (m_leftMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2864  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2865  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2866  m_leftMeasureType->setText(s);
2867 
2868  if (m_leftMeasure->GetSampleResidual() == Null) {
2869  s = "Sample Residual: Null";
2870  }
2871  else {
2872  s = "Sample Residual: " + QString::number(m_leftMeasure->GetSampleResidual());
2873  }
2874  m_leftSampError->setText(s);
2875  if (m_leftMeasure->GetLineResidual() == Null) {
2876  s = "Line Residual: Null";
2877  }
2878  else {
2879  s = "Line Residual: " + QString::number(m_leftMeasure->GetLineResidual());
2880  }
2881  m_leftLineError->setText(s);
2882 
2883  if (m_leftMeasure->GetSampleShift() == Null) {
2884  s = "Sample Shift: Null";
2885  }
2886  else {
2887  s = "Sample Shift: " + QString::number(m_leftMeasure->GetSampleShift());
2888  }
2889  m_leftSampShift->setText(s);
2890 
2891  if (m_leftMeasure->GetLineShift() == Null) {
2892  s = "Line Shift: Null";
2893  }
2894  else {
2895  s = "Line Shift: " + QString::number(m_leftMeasure->GetLineShift());
2896  }
2897  m_leftLineShift->setText(s);
2898 
2899  double goodnessOfFit = m_leftMeasure->GetLogData(
2900  ControlMeasureLogData::GoodnessOfFit).GetNumericalValue();
2901  if (goodnessOfFit == Null) {
2902  s = "Goodness of Fit: Null";
2903  }
2904  else {
2905  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2906  }
2907  m_leftGoodness->setText(s);
2908 
2909  }
2910 
2911 
2912 
2932 
2933  // Set editLock measure box correctly
2934  m_lockRightMeasure->setChecked(IsMeasureLocked(
2935  m_rightMeasure->GetCubeSerialNumber()));
2936  // Set ignore measure box correctly
2937  m_ignoreRightMeasure->setChecked(m_rightMeasure->IsIgnored());
2938 
2939  QString s = "Reference: ";
2940  if (m_editPoint->IsReferenceExplicit() &&
2941  (QString(m_rightMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2942  s += "True";
2943  }
2944  else {
2945  s += "False";
2946  }
2947 
2948  m_rightReference->setText(s);
2949 
2950  s = "Measure Type: ";
2951  if (m_rightMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2952  if (m_rightMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2953  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2954  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2955  m_rightMeasureType->setText(s);
2956 
2957  if (m_rightMeasure->GetSampleResidual() == Null) {
2958  s = "Sample Residual: Null";
2959  }
2960  else {
2961  s = "Sample Residual: " + QString::number(m_rightMeasure->GetSampleResidual());
2962  }
2963  m_rightSampError->setText(s);
2964  if (m_rightMeasure->GetLineResidual() == Null) {
2965  s = "Line Residual: Null";
2966  }
2967  else {
2968  s = "Line Residual: " + QString::number(m_rightMeasure->GetLineResidual());
2969  }
2970  m_rightLineError->setText(s);
2971 
2972  if (m_rightMeasure->GetSampleShift() == Null) {
2973  s = "Sample Shift: Null";
2974  }
2975  else {
2976  s = "Sample Shift: " + QString::number(m_rightMeasure->GetSampleShift());
2977  }
2978  m_rightSampShift->setText(s);
2979 
2980  if (m_rightMeasure->GetLineShift() == Null) {
2981  s = "Line Shift: Null";
2982  }
2983  else {
2984  s = "Line Shift: " + QString::number(m_rightMeasure->GetLineShift());
2985  }
2986  m_rightLineShift->setText(s);
2987 
2988  double goodnessOfFit = m_rightMeasure->GetLogData(
2989  ControlMeasureLogData::GoodnessOfFit).GetNumericalValue();
2990  if (goodnessOfFit == Null) {
2991  s = "Goodness of Fit: Null";
2992  }
2993  else {
2994  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2995  }
2996  m_rightGoodness->setText(s);
2997 
2998  }
2999 
3000 
3016 
3017  // Create list of list box of all files highlighting those that
3018  // contain the point, but that do not already have a measure.
3019  QStringList pointFiles;
3020 
3021  // Initialize camera for all images in control network,
3022  // TODO:: Needs to be moved to QnetFileTool.cpp
3023  Camera *cam;
3024 
3025  // Use lat/lon of first measure
3026  double lat;
3027  double lon;
3028 
3029  ControlMeasure m = *(m_editPoint->GetRefMeasure());
3030  int camIndex = m_serialNumberList->serialNumberIndex(m.GetCubeSerialNumber());
3031  cam = m_controlNet->Camera(camIndex);
3032  //cam = m.Camera();
3033  cam->SetImage(m.GetSample(),m.GetLine());
3034  lat = cam->UniversalLatitude();
3035  lon = cam->UniversalLongitude();
3036 
3037  for (int i=0; i<m_serialNumberList->size(); i++) {
3038  cam = m_controlNet->Camera(i);
3039  if (m_serialNumberList->serialNumber(i) == m_groundSN) continue;
3040  if (cam->SetUniversalGround(lat,lon)) {
3041  // Make sure point is within image boundary
3042  double samp = cam->Sample();
3043  double line = cam->Line();
3044  if (samp >= 1 && samp <= cam->Samples() &&
3045  line >= 1 && line <= cam->Lines()) {
3046  pointFiles<<m_serialNumberList->fileName(i);
3047  }
3048  }
3049  }
3050 
3051  QnetNewMeasureDialog *newMeasureDialog = new QnetNewMeasureDialog(this);
3052  newMeasureDialog->setFiles(*m_editPoint,pointFiles);
3053  if (newMeasureDialog->exec()) {
3054  QStringList selectedFiles = newMeasureDialog->selectedFiles();
3055  foreach (QString selectedFile, selectedFiles) {
3056  // Create measure for any file selected
3057  ControlMeasure *m = new ControlMeasure;
3058  // Find serial number for this file
3059  QString sn = m_serialNumberList->serialNumber(selectedFile);
3060  m->SetCubeSerialNumber(sn);
3061  int camIndex =
3062  m_serialNumberList->fileNameIndex(selectedFile);
3063  cam = m_controlNet->Camera(camIndex);
3064  cam->SetUniversalGround(lat,lon);
3065  m->SetCoordinate(cam->Sample(),cam->Line());
3066  m->SetAprioriSample(cam->Sample());
3067  m->SetAprioriLine(cam->Line());
3070  m_editPoint->Add(m);
3071  }
3072  loadPoint();
3073  m_qnetTool->setVisible(true);
3074  m_qnetTool->raise();
3075 
3077  m_pointEditor->templateFileName());
3078 
3079 
3080  // emit signal so the nav tool can update edit point
3081  emit editPointChanged(m_editPoint->GetId());
3083  }
3084  }
3085 
3086 
3097  bool QnetTool::eventFilter(QObject *o, QEvent *e) {
3098  if(e->type() != QEvent::Leave) return false;
3099  if(o == m_leftCombo->view()) {
3101  m_leftCombo->hidePopup();
3102  }
3103  if (o == m_rightCombo->view()) {
3105  m_rightCombo->hidePopup();
3106  }
3107  return true;
3108  }
3109 
3110 
3118  void QnetTool::paintViewport(MdiCubeViewport *vp, QPainter *painter) {
3119  drawAllMeasurments (vp,painter);
3120 
3121  }
3122 
3123 
3137  void QnetTool::paintAllViewports(QString pointId) {
3138 
3139  // Take care of drawing things on all viewPorts.
3140  // Calling update will cause the Tool class to call all registered tools
3141  // if point has been deleted, this will remove it from the main window
3142  MdiCubeViewport *vp;
3143  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
3144  vp = (*(cubeViewportList()))[i];
3145  vp->viewport()->update();
3146  }
3147  }
3148 
3171  void QnetTool::drawAllMeasurments(MdiCubeViewport *vp, QPainter *painter) {
3172  // Without a controlnetwork there are no points, or if new net, no points
3173  if (m_controlNet == 0 || m_controlNet->GetNumPoints() == 0) return;
3174 
3175  // Don't show the measurments on cubes not in the serial number list
3176  // TODO: Should we show them anyway
3177  // TODO: Should we add the SN to the viewPort
3178  QString serialNumber = SerialNumber::Compose(*vp->cube(), true);
3179 
3180  if (serialNumber == m_groundSN) {
3181  drawGroundMeasures(vp, painter);
3182  return;
3183  }
3184  if (!m_controlNet->GetCubeSerials().contains(
3185  serialNumber)) return;
3186  if (!m_serialNumberList->hasSerialNumber(serialNumber)) return;
3187  QList<ControlMeasure *> measures =
3188  m_controlNet->GetMeasuresInCube(serialNumber);
3189  // loop through all measures contained in this cube
3190  for (int i = 0; i < measures.count(); i++) {
3191  ControlMeasure *m = measures[i];
3192  // Find the measurments on the viewport
3193  double samp = m->GetSample();
3194  double line = m->GetLine();
3195  int x, y;
3196  vp->cubeToViewport(samp, line, x, y);
3197  // if the point is ignored,
3198  if (m->Parent()->IsIgnored()) {
3199  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
3200  }
3201  // point is not ignored, but measure matching this image is ignored,
3202  else if (m->IsIgnored()) {
3203  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
3204  }
3205  // Neither point nor measure is not ignored and the measure is fixed,
3206  else if (m->Parent()->GetType() != ControlPoint::Free) {
3207  painter->setPen(Qt::magenta);// set point marker magenta
3208  }
3209  else {
3210  painter->setPen(Qt::green); // set all other point markers green
3211  }
3212  // draw points
3213  painter->drawLine(x - 5, y, x + 5, y);
3214  painter->drawLine(x, y - 5, x, y + 5);
3215  }
3216  // if QnetTool is open,
3217  if (m_editPoint != NULL) {
3218  // and the selected point is in the image,
3219  if (m_editPoint->HasSerialNumber(serialNumber)) {
3220  // find the measurement
3221  double samp = (*m_editPoint)[serialNumber]->GetSample();
3222  double line = (*m_editPoint)[serialNumber]->GetLine();
3223  int x, y;
3224  vp->cubeToViewport(samp, line, x, y);
3225  // set point marker red
3226  QBrush brush(Qt::red);
3227  // set point marker bold - line width 2
3228  QPen pen(brush, 2);
3229  // draw the selected point in each image last so it's on top of the rest of the points
3230  painter->setPen(pen);
3231  painter->drawLine(x - 5, y, x + 5, y);
3232  painter->drawLine(x, y - 5, x, y + 5);
3233  }
3234  }
3235  }
3236 
3237 
3238 
3239 
3249  void QnetTool::drawGroundMeasures(MdiCubeViewport *vp, QPainter *painter) {
3250 
3251  // loop through control network looking for fixed and constrained points
3252  for (int i = 0; i < m_controlNet->GetNumPoints(); i++) {
3253  ControlPoint &p = *((*m_controlNet)[i]);
3254  if (p.GetType() == ControlPoint::Free) continue;
3255  if (!p.HasAprioriCoordinates()) continue;
3256 
3257  // Find the measure on the ground image
3258  if (m_groundGmap->SetGround(p.GetAprioriSurfacePoint().GetLatitude(),
3259  p.GetAprioriSurfacePoint().GetLongitude())) {
3260  double samp = m_groundGmap->Sample();
3261  double line = m_groundGmap->Line();
3262  int x, y;
3263  vp->cubeToViewport(samp, line, x, y);
3264  // if the point is ignored,
3265  if (p.IsIgnored()) {
3266  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
3267  }
3268  else if (p.GetType() != ControlPoint::Free) {
3269  painter->setPen(Qt::magenta);// set point marker magenta
3270  }
3271  else if (&p == m_editPoint) {
3272  // set point marker red
3273  QBrush brush(Qt::red);
3274  // set point marker bold - line width 2
3275  QPen pen(brush, 2);
3276  }
3277  else {
3278  painter->setPen(Qt::green); // set all other point markers green
3279  }
3280  // draw points
3281  painter->drawLine(x - 5, y, x + 5, y);
3282  painter->drawLine(x, y - 5, x, y + 5);
3283  }
3284  }
3285  }
3286 
3287 
3288 
3302 
3303  if (m_templateModified) {
3304  int r = QMessageBox::warning(m_qnetTool, tr("OK to continue?"),
3305  tr("The currently opened registration template has been modified.\n"
3306  "Save changes?"),
3307  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
3308  QMessageBox::Yes);
3309 
3310  if (r == QMessageBox::Yes)
3312  else if (r == QMessageBox::Cancel)
3313  return false;
3314  }
3315 
3316  return true;
3317  }
3318 
3319 
3326 
3327  if (!okToContinue())
3328  return;
3329 
3330  QString filename = QFileDialog::getOpenFileName(m_qnetTool,
3331  "Select a registration template", ".",
3332  "Registration template files (*.def *.pvl);;All files (*)");
3333 
3334  if (filename.isEmpty())
3335  return;
3336 
3337  if (m_pointEditor->setTemplateFile(filename)) {
3338  loadTemplateFile(filename);
3339  }
3340  }
3341 
3342 
3348  void QnetTool::loadTemplateFile(QString fn) {
3349 
3350  QFile file(FileName(fn).expanded());
3351  if (!file.open(QIODevice::ReadOnly)) {
3352  QString msg = "Failed to open template file \"" + fn + "\"";
3353  QMessageBox::warning(m_qnetTool, "IO Error", msg);
3354  return;
3355  }
3356 
3357  QTextStream stream(&file);
3358  m_templateEditor->setText(stream.readAll());
3359  file.close();
3360 
3361  QScrollBar * sb = m_templateEditor->verticalScrollBar();
3362  sb->setValue(sb->minimum());
3363 
3364  m_templateModified = false;
3365  m_saveTemplateFile->setEnabled(false);
3366  m_templateFileNameLabel->setText("Template File: " + fn);
3367  }
3368 
3369 
3372  m_templateModified = true;
3373  m_saveTemplateFile->setEnabled(true);
3374  }
3375 
3376 
3379 
3380  if (!m_templateModified)
3381  return;
3382 
3383  QString filename = m_pointEditor->templateFileName();
3384 
3385  writeTemplateFile(filename);
3386  }
3387 
3388 
3391 
3392  QString filename = QFileDialog::getSaveFileName(m_qnetTool,
3393  "Save registration template", ".",
3394  "Registration template files (*.def *.pvl);;All files (*)");
3395 
3396  if (filename.isEmpty())
3397  return;
3398 
3399  writeTemplateFile(filename);
3400  }
3401 
3402 
3408  void QnetTool::writeTemplateFile(QString fn) {
3409 
3410  QString contents = m_templateEditor->toPlainText();
3411 
3412  // catch errors in Pvl format when populating pvl object
3413  stringstream ss;
3414  ss << contents;
3415  try {
3416  Pvl pvl;
3417  ss >> pvl;
3418  }
3419  catch(IException &e) {
3420  QString message = e.toString();
3421  QMessageBox::warning(m_qnetTool, "Error", message);
3422  return;
3423  }
3424 
3425  QString expandedFileName(FileName(fn).expanded());
3426 
3427  QFile file(expandedFileName);
3428 
3429  if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
3430  QString msg = "Failed to save template file to \"" + fn + "\"\nDo you "
3431  "have permission?";
3432  QMessageBox::warning(m_qnetTool, "IO Error", msg);
3433  return;
3434  }
3435 
3436  // now save contents
3437  QTextStream stream(&file);
3438  stream << contents;
3439  file.close();
3440 
3441  if (m_pointEditor->setTemplateFile(fn)) {
3442  m_templateModified = false;
3443  m_saveTemplateFile->setEnabled(false);
3444  m_templateFileNameLabel->setText("Template File: " + fn);
3445  }
3446  }
3447 
3448 
3463  try{
3464  // Get the template file from the ControlPointEditor object
3465  Pvl templatePvl(m_pointEditor->templateFileName());
3466  // Create registration dialog window using PvlEditDialog class
3467  // to view and/or edit the template
3468  PvlEditDialog registrationDialog(templatePvl);
3469  registrationDialog.setWindowTitle("View or Edit Template File: "
3470  + templatePvl.fileName());
3471  registrationDialog.resize(550,360);
3472  registrationDialog.exec();
3473  }
3474  catch (IException &e) {
3475  QString message = e.toString();
3476  QMessageBox::information(m_qnetTool, "Error", message);
3477  }
3478  }
3479 
3480 
3481 
3489  m_pointEditor->saveChips();
3490  }
3491 
3492 
3493  void QnetTool::showHideTemplateEditor() {
3494 
3495  if (!m_templateEditorWidget)
3496  return;
3497 
3498  m_templateEditorWidget->setVisible(!m_templateEditorWidget->isVisible());
3499  }
3500 
3501 
3502 
3515  void QnetTool::updatePointInfo(QString pointId) {
3516  if (m_editPoint == NULL) return;
3517  if (pointId != m_editPoint->GetId()) return;
3518  // The edit point has been changed by SetApriori, so m_editPoint needs
3519  // to possibly update some values. Need to retain measures from m_editPoint
3520  // because they might have been updated, but not yet saved to the network
3521  // ("Save Point").
3522  ControlPoint *updatedPoint = m_controlNet->GetPoint(pointId);
3523  m_editPoint->SetEditLock(updatedPoint->IsEditLocked());
3524  m_editPoint->SetIgnored(updatedPoint->IsIgnored());
3525  m_editPoint->SetAprioriSurfacePoint(updatedPoint->GetAprioriSurfacePoint());
3526 
3527  // Set EditLock box correctly
3528  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
3529 
3530  // Set ignore box correctly
3531  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
3532 
3534 
3535  }
3536 
3537 
3538 
3539 
3556 
3557 
3558  // Check point being edited, make sure it still exists, if not ???
3559  // Update ignored checkbox??
3560  if (m_editPoint != NULL) {
3561  try {
3562  QString id = m_ptIdValue->text().remove("Point ID: ");
3563  m_controlNet->GetPoint(id);
3564  }
3565  catch (IException &) {
3566  delete m_editPoint;
3567  m_editPoint = NULL;
3568  emit editPointChanged("");
3569  m_qnetTool->setVisible(false);
3570  m_measureWindow->setVisible(false);
3571  }
3572  }
3573 
3574  if (m_editPoint == NULL) {
3575  paintAllViewports("");
3576  }
3577  else {
3578  paintAllViewports(m_editPoint->GetId());
3579  }
3580  }
3581 
3582 
3590  void QnetTool::showNavWindow(bool checked){
3591  emit showNavTool();
3592  }
3593 
3607  QWidget *QnetTool::createToolBarWidget (QStackedWidget *parent) {
3608  QWidget *hbox = new QWidget(parent);
3609 
3610  QToolButton *showNavToolButton = new QToolButton();
3611  showNavToolButton->setText("Show Nav Tool");
3612  showNavToolButton->setToolTip("Shows the Navigation Tool Window");
3613  QString text =
3614  "<b>Function:</b> This button will bring up the Navigation Tool window that allows \
3615  the user to view, modify, ignore, delete, or filter points and cubes.";
3616  showNavToolButton->setWhatsThis(text);
3617  connect(showNavToolButton,SIGNAL(clicked(bool)),this,SLOT(showNavWindow(bool)));
3618 
3619  QHBoxLayout *layout = new QHBoxLayout(hbox);
3620  layout->setMargin(0);
3621  layout->addWidget(showNavToolButton);
3622  layout->addStretch(1);
3623  hbox->setLayout(layout);
3624  return hbox;
3625  }
3626 
3627 
3628 
3629 
3649 
3650  QString filter = "Isis cubes (*.cub *.cub.*);;";
3651  filter += "Detached labels (*.lbl);;";
3652  filter += "All (*)";
3653 
3654  QString ground = QFileDialog::getOpenFileName((QWidget*)parent(),
3655  "Open ground source",
3656  ".",
3657  filter);
3658  if (ground.isEmpty()) return;
3659 
3660  // First off, find serial number of new ground, it is needed for a couple of error checks.
3661  QString newGroundSN = SerialNumber::Compose(ground, true);
3662 
3663  // If new ground same file as old ground file simply set as active window.
3664  if (m_groundOpen && m_groundFile == FileName(ground).name()) {
3665  // See if ground source is already opened in a cubeviewport. If so, simply
3666  // activate the viewport and return.
3667  MdiCubeViewport *vp;
3668  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
3669  vp = (*(cubeViewportList()))[i];
3670  if (vp->cube()->fileName() == ground) {
3671  m_workspace->mdiArea()->setActiveSubWindow(
3672  (QMdiSubWindow *)vp->parentWidget()->parent());
3673  return;
3674  }
3675  }
3676  }
3677 
3678  // Make sure there are not serial number conflicts. If there are serial number conflicts,
3679  // simply return, retaining current ground source.
3680  if (newGroundSN != m_groundSN && m_serialNumberList->hasSerialNumber(newGroundSN)) {
3681  // TODO If it already exists, are the files different? Now what?
3682  // For now, do not allow.
3683  QString message = "A cube in the cube list has the same serial number as this ground file. ";
3684  message += "If this ground source is a level 1, un-projected cube, it is probably included ";
3685  message += "in the cube list. If the ground source is a projected version of a cube in ";
3686  message += "the list and has the Instrument Group in the labels, the un-projected and ";
3687  message += "projected cube will have the same serial number. \n";
3688  message += "Because of duplicate serial numbers this cube cannot be used as a ground ";
3689  message += "source.\n\n";
3690  message += "NOTE: If this cube is the reference cube you can select points in ";
3691  message += "the Navigator window, then select the Set Apriori button to use this cube to ";
3692  message += "set the apriori latitude, longitude and radius.";
3693  QMessageBox::critical(m_qnetTool, "Cannot set ground source", message);
3694  return;
3695  }
3696 
3697  // So far, so good. If previous ground, clear out ground source info.
3698  if (m_groundOpen) {
3699  // ....otherwise if new ground source, close old. We only want a single
3700  // ground source opened at once. Delete old ground source from left/right
3701  // combo if it's there, and delete from serial number list.
3702  clearGroundSource ();
3703  }
3704 
3705  QApplication::setOverrideCursor(Qt::WaitCursor);
3706 
3707  // Create new ground cube, if failure, there will be not ground source, clear all ground
3708  // source data. (Cannot call clearGroundSource because it assumes a ground was successfully
3709  // loaded)
3710  m_groundCube.reset(NULL);
3711  m_groundGmap.reset(NULL);
3712 
3713  try {
3714  QScopedPointer<Cube> newGroundCube(new Cube(ground, "r"));
3715  QScopedPointer<UniversalGroundMap> newGroundGmap(new UniversalGroundMap(*newGroundCube));
3716 
3717  m_groundFile = FileName(newGroundCube->fileName()).name();
3718  m_groundCube.reset(newGroundCube.take());
3719  m_groundGmap.reset(newGroundGmap.take());
3720 
3721  m_serialNumberList->add(ground, true);
3722  }
3723  catch (IException &e) {
3724  QApplication::restoreOverrideCursor();
3725  QMessageBox::critical(m_qnetTool, "Error", e.toString());
3726 
3727  m_groundFile.clear();
3728 
3729  // Re-load point w/o ground source
3730  if (m_editPoint) {
3731  loadPoint();
3732  }
3733 
3734  emit refreshNavList();
3735  return;
3736  }
3737 
3738  m_groundSN = newGroundSN;
3739  m_groundSourceFile = ground;
3740  m_groundOpen = true;
3741 
3742  m_workspace->addCubeViewport(m_groundCube.data());
3743 
3744  // Get viewport so connect can be made when ground source viewport closed to clean up
3745  // ground source
3746  MdiCubeViewport *vp;
3747  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
3748  vp = (*(cubeViewportList()))[i];
3749  if (vp->cube()->fileName() == ground) {
3750  connect(vp, SIGNAL(viewportClosed(CubeViewport *)),
3751  this, SLOT(groundViewportClosed(CubeViewport *)), Qt::UniqueConnection);
3752  }
3753  }
3754 
3755  if (!m_demOpen) {
3756  // If there isn't a radius source already open and there is a point selected
3757  if (m_editPoint != NULL) {
3759  }
3760 
3761  // Determine file type of ground for setting AprioriSurfacePointSource
3762  // and AprioriRadiusSource.
3763  else if (m_groundCube->hasTable("ShapeModelStatistics")) {
3764  m_groundSurfacePointSource = ControlPoint::SurfacePointSource::Basemap;
3765  if (!m_demOpen) {
3766  m_groundRadiusSource = ControlPoint::RadiusSource::DEM;
3767  m_radiusSourceFile = ground;
3768  }
3769  }
3770  // Is this a level 1 or level 2?
3771  else {
3772  try {
3773  ProjectionFactory::CreateFromCube(*m_groundCube);
3774  m_groundSurfacePointSource = ControlPoint::SurfacePointSource::Basemap;
3775  if (!m_demOpen) {
3776  m_groundRadiusSource = ControlPoint::RadiusSource::Ellipsoid;
3777  m_radiusSourceFile = "";
3778  }
3779  }
3780  catch (IException &) {
3781  try {
3782  CameraFactory::Create(*m_groundCube);
3783  m_groundSurfacePointSource = ControlPoint::SurfacePointSource::Reference;
3784  if (!m_demOpen) {
3785  PvlGroup kernels = m_groundCube->group("Kernels");
3786  QString shapeFile = kernels ["ShapeModel"];
3787  if (shapeFile.contains("dem")) {
3788  m_groundRadiusSource = ControlPoint::RadiusSource::DEM;
3789  m_radiusSourceFile = shapeFile;
3790  }
3791  else {
3792  m_groundRadiusSource = ControlPoint::RadiusSource::Ellipsoid;
3793  // Find pck file from Kernels group
3794  m_radiusSourceFile = (QString) kernels["TargetAttitudeShape"];
3795  }
3796  }
3797  }
3798  catch (IException &) {
3799  QString message = "Cannot create either Camera or Projections ";
3800  message += "for the ground source file. Check the validity of the ";
3801  message += " cube labels. The cube must either be projected or ";
3802  message += " run through spiceinit.";
3803  QMessageBox::critical(m_qnetTool, "Error", message);
3804  // Clear out everything relating to ground source
3805  clearGroundSource ();
3806  QApplication::restoreOverrideCursor();
3807  emit refreshNavList();
3808  return;
3809  }
3810  }
3811  }
3812  }
3813 
3814  if (m_editPoint != NULL &&
3815  (m_editPoint->GetType() != ControlPoint::Free)) loadPoint();
3816 
3817 
3818  emit refreshNavList();
3819  QApplication::restoreOverrideCursor();
3820  }
3821 
3822 
3831 
3832  if (m_groundFile.isEmpty()) {
3833  QString message = "You must enter a ground source before opening a Dem.";
3834  QMessageBox::critical(m_qnetTool, "Error", message);
3835  return;
3836  }
3837 
3838  QString filter = "Isis cubes (*.cub *.cub.*);;";
3839  filter += "Detached labels (*.lbl);;";
3840  filter += "All (*)";
3841  QString dem = QFileDialog::getOpenFileName((QWidget*)parent(),
3842  "Open DEM",
3843  ".",
3844  filter);
3845  if (dem.isEmpty()) return;
3846 
3847  initDem(dem);
3848 
3849  }
3850 
3859  //Get the reference image's shape model
3860  QString referenceSN = m_editPoint->GetReferenceSN();
3861  QString referenceFileName = m_serialNumberList->fileName(referenceSN);
3862  QScopedPointer<Cube> referenceCube(new Cube(referenceFileName, "r"));
3863  PvlGroup kernels = referenceCube->group("Kernels");
3864  QString shapeFile = kernels["ShapeModel"];
3865 
3866  // If the reference measure has a shape model cube then set that as the radius
3867  // This will NOT WORK for shape model files (not the default of Null or Ellipsoid)
3868  // that are not cubes
3869  if (shapeFile.contains(".cub")) {
3870  if (shapeFile.contains("dem")) {
3871  m_groundRadiusSource = ControlPoint::RadiusSource::DEM;
3872  }
3873  else {
3874  m_groundRadiusSource = ControlPoint::RadiusSource::Ellipsoid;
3875  }
3876 
3877  m_radiusSourceFile = shapeFile;
3878 
3879  // Open shape file for reading radius later
3880  initDem(shapeFile); //This will write the labels for us
3881  }
3882 
3883  // If no shape model then use the ABC of the target body
3884  else {
3885  m_groundRadiusSource = ControlPoint::RadiusSource::Ellipsoid;
3886  Spice *refSpice = new Spice(*referenceCube);
3887  Distance refRadii[3];
3888  refSpice->radii(refRadii);
3889  m_demFile = QString::number(refRadii[0].meters()) + ", " +
3890  QString::number(refRadii[1].meters()) + ", " +
3891  QString::number(refRadii[2].meters());
3892 
3893  m_radiusSourceFile = "";
3894 
3895  // Write out the labels
3896  m_groundFileNameLabel->setText("Ground Source File: " + m_groundFile);
3897  m_radiusFileNameLabel->setText("Radius Source: " + m_demFile);
3898  }
3899  }
3900 
3901  void QnetTool::initDem (QString demFile) {
3902 
3903  // If a DEM is already opened, check if new is same as old. If new,
3904  // close old, open new.
3905  QApplication::setOverrideCursor(Qt::WaitCursor);
3906  if (m_demOpen) {
3907  if (m_demFile == demFile) {
3908  QApplication::restoreOverrideCursor();
3909  return;
3910  }
3911 
3912  m_demCube.reset(NULL);
3913  m_demFile.clear();
3914  }
3915 
3916  try {
3917  QScopedPointer<Cube> newDemCube(new Cube(demFile, "r"));
3918 
3919  m_demFile = FileName(newDemCube->fileName()).name();
3920  m_demCube.reset(newDemCube.take());
3921  }
3922  catch (IException &e) {
3923  QMessageBox::critical(m_qnetTool, "Error", e.toString());
3924  QApplication::restoreOverrideCursor();
3925  return;
3926  }
3927  m_demOpen = true;
3928 
3929  // Make sure this is a dem
3930  if (!m_demCube->hasTable("ShapeModelStatistics")) {
3931  QString message = m_demFile + " is not a DEM.";
3932  QMessageBox::critical(m_qnetTool, "Error", message);
3933  m_demCube.reset(NULL);
3934  m_demOpen = false;
3935  m_demFile.clear();
3936  QApplication::restoreOverrideCursor();
3937  return;
3938  }
3939  m_groundRadiusSource = ControlPoint::RadiusSource::DEM;
3940  m_groundFileNameLabel->setText("Ground Source File: " + m_groundFile);
3941  m_radiusFileNameLabel->setText("Radius Source File: " + m_demFile);
3942  m_radiusSourceFile = demFile;
3943 
3944  QApplication::restoreOverrideCursor();
3945  }
3946 
3947 
3948 
3956 
3957  // Only continue to clearGroundSource if the viewport is not already closed
3958  // Otherwise, it could be called twice
3959  clearGroundSource();
3960  }
3961 
3962 
3963 
3964  void QnetTool::clearGroundSource () {
3965 
3966  m_leftCombo->removeItem(m_leftCombo->findText(m_groundFile));
3967  m_rightCombo->removeItem(m_rightCombo->findText(m_groundFile));
3968 
3969  // Close viewport containing ground source
3970  MdiCubeViewport *vp;
3971  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
3972  vp = (*(cubeViewportList()))[i];
3973  if (vp->cube() == m_groundCube.data()) {
3974  // disconnect signal to avoid recursive situartion. When a viewport is closed, a signal
3975  // is emitted which would then call groundViewportClosed, then this method again.
3976  disconnect(vp, SIGNAL(viewportClosed(CubeViewport *)),
3977  this, SLOT(groundViewportClosed(CubeViewport *)));
3978  vp->parentWidget()->parentWidget()->close();
3979  QApplication::processEvents();
3980  break;
3981  }
3982  }
3983  // If we could not find the ground source in the open viewports, user might
3984  // have closed the viewport , reset ground source variables and re-open.
3985  m_groundOpen = false;
3986  m_groundCube.take();
3987  m_groundFile.clear();
3988  m_groundGmap.reset(NULL);
3989 
3990  m_groundFileNameLabel->setText("Ground Source File: ");
3991  if (!m_demOpen) {
3992  m_radiusFileNameLabel->setText("Radius Source File: " + m_demFile);
3993  }
3994 
3995  // Remove from serial number list
3996  m_serialNumberList->remove(m_groundSN);
3997 
3998  // If the loaded point is a fixed point, see if there is a temporary measure
3999  // holding the coordinate information for the currentground source. If so,
4000  // delete this measure and re-load point
4001  if (m_editPoint && m_editPoint->GetType() != ControlPoint::Free &&
4002  m_editPoint->HasSerialNumber(m_groundSN)) {
4003  m_editPoint->Delete(m_groundSN);
4004  m_groundSN = "";
4005  loadPoint();
4006  }
4007  else {
4008  m_groundSN = "";
4009  }
4010  }
4011 
4012 
4013 
4014 
4015 
4023  double QnetTool::demRadius(double latitude, double longitude) {
4024 
4025  if (!m_demOpen) return Null;
4026 
4027  UniversalGroundMap *demMap = new UniversalGroundMap(*m_demCube);
4028  if (!demMap->SetUniversalGround(latitude, longitude)) {
4029  delete demMap;
4030  demMap = NULL;
4031  return Null;
4032  }
4033 
4034  // Use bilinear interpolation to read radius from DEM
4035  // Use bilinear interpolation from dem
4036  Interpolator *interp = new Interpolator(Interpolator::BiLinearType);
4037 
4038  // Buffer used to read from the model
4039  Portal *portal = new Portal(interp->Samples(), interp->Lines(),
4040  m_demCube->pixelType(),
4041  interp->HotSample(), interp->HotLine());
4042  portal->SetPosition(demMap->Sample(), demMap->Line(), 1);
4043  m_demCube->read(*portal);
4044  double radius = interp->Interpolate(demMap->Sample(), demMap->Line(),
4045  portal->DoubleBuffer());
4046  delete demMap;
4047  demMap = NULL;
4048  delete interp;
4049  interp = NULL;
4050  delete portal;
4051  portal = NULL;
4052 
4053 // cout.width(15);
4054 // cout.precision(4);
4055 // cout<<"DEM Radius = "<<fixed<<radius<<endl;
4056  return radius;
4057  }
4058 
4059 
4060 
4067 
4068  QColor qc = Qt::red;
4069  QPalette p = m_savePoint->palette();
4070  p.setColor(QPalette::ButtonText,qc);
4071  m_savePoint->setPalette(p);
4072 
4073  }
4074 
4075 
4076 
4089  bool QnetTool::IsMeasureLocked (QString serialNumber) {
4090 
4091  if (m_editPoint == NULL) return false;
4092 
4093  // Reference implicitly editLocked
4094  if (m_editPoint->IsEditLocked() && m_editPoint->IsReferenceExplicit() &&
4095  (m_editPoint->GetReferenceSN() == serialNumber)) {
4096  return true;
4097  }
4098  // Return measures explicit editLocked value
4099  else {
4100  return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
4101  }
4102 
4103  }
4104 
4105 
4106 
4113  FileName config("$HOME/.Isis/qnet/QnetTool.config");
4114  QSettings settings(config.expanded(), QSettings::NativeFormat);
4115  QPoint pos = settings.value("pos", QPoint(300, 100)).toPoint();
4116  QSize size = settings.value("size", QSize(900, 500)).toSize();
4117  m_qnetTool->resize(size);
4118  m_qnetTool->move(pos);
4119  }
4120 
4121 
4129  /*We do not want to write the settings unless the window is
4130  visible at the time of closing the application*/
4131  if(!m_qnetTool->isVisible()) return;
4132  FileName config("$HOME/.Isis/qnet/QnetTool.config");
4133  QSettings settings(config.expanded(), QSettings::NativeFormat);
4134  settings.setValue("pos", m_qnetTool->pos());
4135  settings.setValue("size", m_qnetTool->size());
4136  }
4137 
4138 
4139 
4140  void QnetTool::enterWhatsThisMode() {
4141  QWhatsThis::enterWhatsThisMode();
4142  }
4143 
4144 
4145 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:148
Status SetType(MeasureType type)
Set how the coordinate was obtained.
Cube display widget for certain Isis MDI applications.
void loadGroundMeasure()
Load ground measure into right side and add to file combo boxes.
Definition: QnetTool.cpp:1185
bool HasSerialNumber(QString serialNumber) const
Return true if given serial number exists in point.
double meters() const
Get the distance in meters.
Definition: Distance.cpp:97
void setIgnorePoint(bool ignore)
Set point&#39;s "Ignore" keyword to the value of the input parameter.
Definition: QnetTool.cpp:1239
bool checkReference()
Change which measure is the reference.
Definition: QnetTool.cpp:864
double HotSample()
Returns the sample coordinate of the center pixel in the buffer for the interpolator.
int serialNumberIndex(const QString &sn)
Return a list index given a serial number.
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition: Buffer.h:154
void setLockLeftMeasure(bool ignore)
Set the "EditLock" keyword of the measure shown in the left viewport to the value of the input parame...
Definition: QnetTool.cpp:1272
void updateSurfacePointInfo()
Update the Surface Point Information in the QnetTool window.
Definition: QnetTool.cpp:2615
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:127
double Line() const
Returns the current line value of the camera model or projection.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
Cube * cube() const
Definition: CubeViewport.h:348
void Add(ControlMeasure *measure)
Add a measurement to the control point, taking ownership of the measure in the process.
(e.g., autoseed, interest) AKA predicted, unmeasured, unverified
QGroupBox * createControlPointGroupBox()
Definition: QnetTool.cpp:265
void updateNet(QString cNetFileName)
Updates the Control Network displayed in the Qnet Tool title bar.
Definition: QnetTool.cpp:1453
bool hasSerialNumber(QString sn)
Determines whether or not the requested serial number exists in the list.
void modifyPoint(ControlPoint *point)
Modify control point.
Definition: QnetTool.cpp:2109
A Constrained point is a Control Point whose lat/lon/radius is somewhat established and should not be...
Definition: ControlPoint.h:391
A Fixed point is a Control Point whose lat/lon is well established and should not be changed...
Definition: ControlPoint.h:386
double Interpolate(const double isamp, const double iline, const double buf[])
Performs an interpolation on the data according to the parameters set in the constructor.
File name manipulation and expansion.
Definition: FileName.h:116
Universal Ground Map.
QWidget * createToolBarWidget(QStackedWidget *parent)
This method creates the widgets for the tool bar.
Definition: QnetTool.cpp:3607
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
void mouseButtonRelease(QPoint p, Qt::MouseButton s)
Handle mouse events on CubeViewport.
Definition: QnetTool.cpp:1519
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition: Tool.cpp:390
Buffer for containing a two dimensional section of an image.
Definition: Portal.h:52
void saveChips()
Slot which calls ControlPointEditor slot to save chips.
Definition: QnetTool.cpp:3488
void openReferenceRadius()
Open a radius source using the shape model of the reference measure of m_editPoint.
Definition: QnetTool.cpp:3858
void drawGroundMeasures(MdiCubeViewport *vp, QPainter *painter)
Draw all Fixed or Constrained points on the ground source viewport.
Definition: QnetTool.cpp:3249
QString serialNumber(const QString &filename)
Return a serial number given a filename.
double GetResidualMagnitude() const
Return Residual magnitude.
PointType
These are the valid &#39;types&#39; of point.
Definition: ControlPoint.h:379
bool findPointLocation()
Attempt to find the control point&#39;s location on the ground source.
Definition: QnetTool.cpp:2161
Namespace for the standard library.
void nextRightMeasure()
Selects the next right measure when activated by key shortcut.
Definition: QnetTool.cpp:2724
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:63
Distance GetLatSigmaDistance() const
Return the latitude sigma as a Distance.
void openTemplateFile()
prompt user for a registration template file to open.
Definition: QnetTool.cpp:3325
void paintViewport(MdiCubeViewport *cvp, QPainter *painter)
Take care of drawing things on a viewPort.
Definition: QnetTool.cpp:3118
void setPointType(int pointType)
Set the point type.
Definition: QnetTool.cpp:1119
int fileNameIndex(const QString &filename)
Return a list index given a filename.
Status SetChooserName(QString name)
Set the point&#39;s chooser name.
void saveNet()
Signal to save control net.
Definition: QnetTool.cpp:1404
void setTemplateModified()
called when the template file is modified by the template editor
Definition: QnetTool.cpp:3371
Widget to display Isis cubes for qt apps.
Definition: CubeViewport.h:132
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
Distance GetLonSigmaDistance() const
Return the longitude sigma in meters.
Registered to whole pixel (e.g.,pointreg)
Registered to sub-pixel (e.g., pointreg)
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
void selectLeftMeasure(int index)
Select left measure.
Definition: QnetTool.cpp:2765
void refresh()
Refresh all necessary widgets in QnetTool including the PointEditor and CubeViewports.
Definition: QnetTool.cpp:3555
void createFixedPoint(double lat, double lon)
Create new Fixed control point.
Definition: QnetTool.cpp:1786
Distance measurement, usually in meters.
Definition: Distance.h:47
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
QGroupBox * createLeftMeasureGroupBox()
Definition: QnetTool.cpp:331
void savePoint()
Save edit point to the Control Network.
Definition: QnetTool.cpp:1060
void paintAllViewports(QString pointId)
This method will repaint the given Point ID in each viewport Note: The pointId parameter is here even...
Definition: QnetTool.cpp:3137
A Free point is a Control Point that identifies common measurements between two or more cubes...
Definition: ControlPoint.h:399
bool okToContinue()
Allows user to set a new template file.
Definition: QnetTool.cpp:3301
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
QString fileName(const QString &sn)
Return a filename given a serial number.
This was called the Qisis MainWindow.
void updateLeftMeasureInfo()
Definition: QnetTool.cpp:2843
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:396
QAction * toolPadAction(ToolPad *pad)
Adds the Tie tool action to the tool pad.
Definition: QnetTool.cpp:1474
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
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
void createQnetTool(QWidget *parent)
create the main window for editing control points
Definition: QnetTool.cpp:131
double HotLine()
Returns the line coordinate of the center pixel in the buffer for the interpolator.
void addMeasure()
Add measure to point.
Definition: QnetTool.cpp:3015
void loadTemplateFile(QString)
Updates the current template file being used.
Definition: QnetTool.cpp:3348
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
a control network
Definition: ControlNet.h:271
Hand Measured (e.g., qnet)
QString GetId() const
Return the Id of the control point.
Status SetCamera(Isis::Camera *camera)
Set pointer to camera associated with a measure.
int Samples()
Returns the number of samples needed by the interpolator.
void setFiles(ControlPoint point, QStringList pointFiles)
Pixel value mapper.
Definition: Stretch.h:72
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
UniversalGroundMap * universalGroundMap() const
Definition: CubeViewport.h:363
void saveTemplateFileAs()
save the contents of template editor to a file chosen by the user
Definition: QnetTool.cpp:3390
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
void createPoint(double lat, double lon)
Create new control point.
Definition: QnetTool.cpp:1671
ControlMeasure * createTemporaryGroundMeasure()
Create a temporary measure to hold the ground point info for ground source.
Definition: QnetTool.cpp:2207
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2702
Status SetAprioriSurfacePoint(SurfacePoint aprioriSP)
This updates the apriori surface point.
void readSettings()
This method is called from the constructor so that when the Main window is created, it know&#39;s it&#39;s size and location.
Definition: QnetTool.cpp:4112
double UniversalLatitude() const
Returns the universal latitude of the camera model or projection.
void colorizeSaveButton()
Turn "Save Point" button text to red.
Definition: QnetTool.cpp:4066
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
A single control point.
Definition: ControlPoint.h:369
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
void createMenus()
Customize dropdown menus below title bar.
Definition: QnetTool.cpp:626
void setLockRightMeasure(bool ignore)
Set the "EditLock" keyword of the measure shown in the right viewport to the value of the input param...
Definition: QnetTool.cpp:1343
void previousRightMeasure()
Selects the previous right measure when activated by key shortcut.
Definition: QnetTool.cpp:2743
void remove(const QString &sn)
Remove the specified serial number from the list.
void loadPoint()
Load point into QnetTool.
Definition: QnetTool.cpp:2244
Container for cube-like labels.
Definition: Pvl.h:135
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
bool eventFilter(QObject *o, QEvent *e)
Event filter for QnetTool.
Definition: QnetTool.cpp:3097
void setIgnoreRightMeasure(bool ignore)
Set the "Ignore" keyword of the measure shown in the right viewport to the value of the input paramet...
Definition: QnetTool.cpp:1383
void createTemplateEditorWidget()
Creates the Widget which contains the template editor and its toolbar.
Definition: QnetTool.cpp:475
void SetPosition(const double sample, const double line, const int band)
Sets the line and sample position of the buffer.
Definition: Portal.h:109
void saveAsNet()
Signal to save the control net.
Definition: QnetTool.cpp:1420
void writeTemplateFile(QString)
write the contents of the template editor to the file provided.
Definition: QnetTool.cpp:3408
void deletePoint(ControlPoint *point)
Delete control point.
Definition: QnetTool.cpp:1960
int size() const
How many serial number / filename combos are in the list.
Status SetType(PointType newType)
Updates the control point&#39;s type.
void loadMeasureTable()
Load measure information into the measure table.
Definition: QnetTool.cpp:2378
bool SetImage(double sample, double line)
Returns whether the sample/line postion was set successfully in the camera model or projection...
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void measureSaved()
This method is connected with the measureSaved() signal from ControlPointEdit.
Definition: QnetTool.cpp:724
void drawAllMeasurments(MdiCubeViewport *vp, QPainter *painter)
Draw all measurments which are on this viewPort.
Definition: QnetTool.cpp:3171
Status
This is a return status for many of the mutating (setter) method calls.
Definition: ControlPoint.h:408
GoodnessOfFit is pointreg information for reference measures.
void setIgnoreLeftMeasure(bool ignore)
Set the "Ignore" keyword of the measure shown in the left viewport to the value of the input paramete...
Definition: QnetTool.cpp:1313
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:553
int Lines()
Returns the number of lines needed by the interpolator.
Pixel interpolator.
Definition: Interpolator.h:51
void setLockPoint(bool ignore)
Set point&#39;s "EditLock" keyword to the value of the input parameter.
Definition: QnetTool.cpp:1220
void viewTemplateFile()
Allows the user to view the template file that is currently set.
Definition: QnetTool.cpp:3462
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
void setFiles(QStringList pointFiles)
Set files found containing selected point.
double Line()
Returns the current line number.
Definition: Camera.cpp:2722
static QString UserName()
Returns the user name.
Isis exception class.
Definition: IException.h:107
Status SetChooserName()
Set chooser name to a user who last changed the coordinate.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool IsEditLocked() const
Return value for p_editLock or implicit lock on reference measure.
bool SetUniversalGround(double lat, double lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
void showNavWindow(bool checked)
Emits a signal to displays the Navigation window.
Definition: QnetTool.cpp:3590
Base class for the Qisis tools.
Definition: Tool.h:81
a control measurement
PvlEditDialog creates a QDialog window in which a QTextEdit box displays the contents of a pvl file...
Definition: PvlEditDialog.h:39
void setFiles(QStringList pointFiles)
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
Status SetCoordinate(double sample, double line)
Set the coordinate of the measurement.
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:211
Base class for the Qisis main windows.
Definition: MainWindow.h:24
Obtain SPICE information for a spacecraft.
Definition: Spice.h:294
The distance is being specified in meters.
Definition: Distance.h:56
Point Editor Widget.
int Delete(ControlMeasure *measure)
Remove a measurement from the control point, deleting reference measure is allowed.
void openGround()
Open a ground source for selecting fixed points.
Definition: QnetTool.cpp:3648
double GetNumericalValue() const
Get the value associated with this log data.
void updateRightMeasureInfo()
Definition: QnetTool.cpp:2931
double Sample() const
Returns the current line value of the camera model or projection.
void createActions()
Creates the menu actions for Qnet Tool.
Definition: QnetTool.cpp:505
void groundViewportClosed(CubeViewport *)
Slot called when the ground source cube viewport is closed.
Definition: QnetTool.cpp:3955
void saveTemplateFile()
save the file opened in the template editor
Definition: QnetTool.cpp:3378
void writeSettings() const
This method is called when the Main window is closed or hidden to write the size and location setting...
Definition: QnetTool.cpp:4128
PointType GetType() const
Serial Number list generator.
Distance GetLocalRadius() const
Return the radius of the surface point.
double demRadius(double latitude, double longitude)
Return a radius values from the dem using bilinear interpolation.
Definition: QnetTool.cpp:4023
double UniversalLongitude() const
Returns the universal longitude of the camera model or projection.
void radii(Distance r[3]) const
Returns the radii of the body in km.
Definition: Spice.cpp:855
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
QSplitter * createTopSplitter()
creates everything above the ControlPointEdit
Definition: QnetTool.cpp:236
static QString PointTypeToString(PointType type)
Obtain a string representation of a given PointType.
QGroupBox * createRightMeasureGroupBox()
Creates the right measure group box.
Definition: QnetTool.cpp:403
void selectRightMeasure(int index)
Select right measure.
Definition: QnetTool.cpp:2800
void updatePointInfo(QString pointId)
Update the current editPoint information in the Point Editor labels.
Definition: QnetTool.cpp:3515
bool IsMeasureLocked(QString serialNumber)
Check for implicitly locked measure in m_editPoint.
Definition: QnetTool.cpp:4089
void openDem()
Open a DEM for ground source radii.
Definition: QnetTool.cpp:3830
QString GetCubeSerialNumber() const
Return the serial number of the cube containing the coordinate.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
static QString MeasureTypeToString(MeasureType type)
Return the String Control Measure type.
This is returned when the operation requires Edit Lock to be false but it is currently true...
Definition: ControlPoint.h:423
IO Handler for Isis Cubes.
Definition: Cube.h:170