Loading [MathJax]/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
ControlPointEditWidget.cpp
1
6
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "ControlPointEditWidget.h"
10
11#include <iomanip>
12#include <sstream>
13#include <vector>
14
15#include <QAction>
16#include <QCheckBox>
17#include <QComboBox>
18#include <QFileDialog>
19#include <QFileInfo>
20#include <QFormLayout>
21#include <QGroupBox>
22#include <QHBoxLayout>
23#include <QLabel>
24#include <QMainWindow>
25#include <QMessageBox>
26#include <QObject>
27#include <QPushButton>
28#include <QScrollBar>
29#include <QShortcut>
30#include <QSplitter>
31#include <QTableWidget>
32#include <QTextEdit>
33#include <QVBoxLayout>
34
35#include "Application.h"
36#include "Camera.h"
37#include "Control.h"
38#include "ControlMeasureEditWidget.h"
39#include "ControlMeasure.h"
40#include "ControlMeasureLogData.h"
41#include "ControlNet.h"
42#include "ControlPoint.h"
43#include "DeleteControlPointDialog.h"
44#include "Directory.h"
45#include "FileName.h"
46#include "IException.h"
47#include "Latitude.h"
48#include "Longitude.h"
49#include "MainWindow.h"
50#include "MdiCubeViewport.h"
51#include "NewControlPointDialog.h"
52#include "NewGroundSourceLocationDialog.h"
53#include "Project.h"
54#include "Pvl.h"
55#include "PvlEditDialog.h"
56#include "SerialNumber.h"
57#include "SerialNumberList.h"
58#include "Shape.h"
59#include "ShapeList.h"
60#include "SpecialPixel.h"
61#include "Table.h"
62#include "TemplateList.h"
63#include "ToolPad.h"
64#include "UniversalGroundMap.h"
65#include "ViewportMainWindow.h"
66#include "Workspace.h"
67
68using namespace std;
69
70namespace Isis {
79 bool addMeasures) : QWidget(parent) {
80
81 m_directory = directory;
82 m_addMeasuresButton = addMeasures;
83 m_cnetModified = false;
84 m_templateModified = false;
85 m_serialNumberList = NULL;
86 m_editPoint = NULL;
87
90 m_demOpen = false;
91
92 m_parent = parent;
93
95
96 connect(this, SIGNAL(newControlNetwork(ControlNet *)),
97 m_measureEditor, SIGNAL(newControlNetwork(ControlNet *)));
98
99 connect(m_directory->project(), SIGNAL(templatesAdded(TemplateList *)),
100 this, SLOT(addTemplates(TemplateList *)));
101 }
102
103
104 ControlPointEditWidget::~ControlPointEditWidget () {
105
106 }
107
108
109 QString ControlPointEditWidget::editPointId() {
110
111 QString result = "";
112 if (m_editPoint) {
113 result = m_editPoint->GetId();
114 }
115 return result;
116 }
117
118
119 ControlPoint *ControlPointEditWidget::editPoint() {
120
121 ControlPoint *result = NULL;
122 if (m_editPoint) {
123 result = m_editPoint;
124 }
125 return result;
126 }
127
128
154 void ControlPointEditWidget::createPointEditor(QWidget *parent, bool addMeasures) {
155
156 setWindowTitle("Control Point Editor");
157 setObjectName("ControlPointEditWidget");
158 connect(this, SIGNAL(destroyed(QObject *)), this, SLOT(clearEditPoint()));
159
161
162 // create m_measureEditor first since we need to get its templateFileName
163 // later
164 m_measureEditor = new ControlMeasureEditWidget(parent, true, true);
165
166 // TODO Does this need to be moved to ControlNetEditMainWindow???
167 connect(this, SIGNAL(newControlNetwork(ControlNet *)),
168 m_measureEditor, SIGNAL(newControlNetwork(ControlNet *)));
169
170
171 connect(this, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)),
172 m_measureEditor, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)));
173 connect(m_measureEditor, SIGNAL(measureSaved()), this, SLOT(measureSaved()));
174 connect(this, SIGNAL(cnetModified()), this, SLOT(colorizeSaveNetButton()));
175
176 QPushButton *addMeasure = NULL;
178 addMeasure = new QPushButton("Add Measure(s) to Point");
179 addMeasure->setToolTip("Add a new measure to the edit control point.");
180 addMeasure->setWhatsThis("This allows a new control measure to be added "
181 "to the currently edited control point. A selection "
182 "box with all cubes from the input list will be "
183 "displayed with those that intersect with the "
184 "control point highlighted.");
185 //TODO addMeasure() slot is not implemented ???
186 connect(addMeasure, SIGNAL(clicked()), this, SLOT(addMeasure()));
187 }
188
189 m_reloadPoint = new QPushButton("Reload Point");
190 m_reloadPoint->setToolTip("Reload the control point.");
191 m_reloadPoint->setWhatsThis("Reload the measures for the control point"
192 " in the Chip Viewports to its saved values. ");
193 connect(m_reloadPoint, SIGNAL(clicked()), this, SLOT(reloadPoint()));
194
195 m_savePoint = new QPushButton ("Save Point");
196 m_savePoint->setShortcut(Qt::Key_P);
197 m_savePoint->setToolTip("Save the edit control point to the control network. "
198 "<strong>Shortcut: P</strong>");
199 m_savePoint->setWhatsThis("Save the edit control point to the control "
200 "network which is loaded into memory in its entirety. "
201 "When a control point is selected for editing, "
202 "a copy of the point is made so that the original control "
203 "point remains in the network.");
205 connect (m_savePoint, SIGNAL(clicked()), this, SLOT(savePoint()));
206
207 m_saveNet = new QPushButton ("Save Control Net");
208 m_saveNet->setShortcut(Qt::Key_S);
209 m_saveNet->setToolTip("Save current control network. "
210 "<strong>Shortcut: S</strong>");
211 m_savePoint->setWhatsThis("Save the control network.");
212// m_saveDefaultPalette = m_savePoint->palette();
213// This slot is needed because we cannot directly emit a signal with a ControlNet
214// argument after the "Save Net" push button is selected since the parameter list must match.
215// The saveNet slot will simply emit a signal with the ControlNet as the argument.
216 connect (m_saveNet, SIGNAL(clicked()), this, SLOT(saveNet()));
217
218 QHBoxLayout * saveMeasureLayout = new QHBoxLayout;
220 saveMeasureLayout->addWidget(addMeasure);
221 }
222
223 saveMeasureLayout->addWidget(m_reloadPoint);
224 saveMeasureLayout->addWidget(m_savePoint);
225 saveMeasureLayout->addWidget(m_saveNet);
226 saveMeasureLayout->insertStretch(-1);
227
228 m_cnetFileNameLabel = new QLabel("Control Network: " + m_cnetFileName);
229
230 // Create a combobox to allow user to select either the default registration file or one of the
231 // imported registration files.
233 m_templateComboBox->setToolTip("Choose a template file");
234 m_templateComboBox->setWhatsThis("FileName of the sub-pixel "
235 "registration template. Refer to https://astrogeology.usgs.gov/docs/concepts/control-networks/pattern-matching/ for a description of the "
236 "contents of this file.");
237 m_templateComboBox->addItem(m_measureEditor->templateFileName());
238 QList <TemplateList *> regTemplates = m_directory->project()->regTemplates();
239 foreach(TemplateList *templateList, regTemplates) {
240 foreach(Template *templateFile, *templateList){
241 m_templateComboBox->addItem(templateFile->importName()
242 + "/" + FileName(templateFile->fileName()).name());
243 }
244 }
245 QFormLayout *templateFileLayout = new QFormLayout();
246 templateFileLayout->addRow("Template File:", m_templateComboBox);
247
248 // Set-up connections to give registration combobox functionality
249 connect(m_templateComboBox, SIGNAL(activated(QString)),
250 this, SLOT(setTemplateFile(QString)));
251 connect(m_measureEditor, SIGNAL(setTemplateFailed(QString)),
252 this, SLOT(resetTemplateComboBox(QString)));
253
254 QVBoxLayout * centralLayout = new QVBoxLayout;
255
256 centralLayout->addWidget(m_cnetFileNameLabel);
257 centralLayout->addLayout(templateFileLayout);
258 centralLayout->addWidget(createTopSplitter());
259 centralLayout->addStretch();
260 centralLayout->addWidget(m_measureEditor);
261 centralLayout->addLayout(saveMeasureLayout);
262
263 QWidget *centralWidget = new QWidget;
264 centralWidget->setLayout(centralLayout);
265
266 QScrollArea *scrollArea = new QScrollArea();
267 scrollArea->setObjectName("ControlPointEditWidgetScroll");
268 scrollArea->setWidget(centralWidget);
269 scrollArea->setWidgetResizable(true);
270 centralWidget->adjustSize();
271
272 QHBoxLayout *mainLayout = new QHBoxLayout;
273 mainLayout->addWidget(scrollArea);
274 setLayout(mainLayout);
275
276// connect(this, SIGNAL(controlPointChanged()), this, SLOT(paintAllViewports()));
277
278// readSettings();
279 }
280
281
288
289 QHBoxLayout * measureLayout = new QHBoxLayout;
290 measureLayout->addWidget(createLeftMeasureGroupBox());
291 measureLayout->addWidget(createRightMeasureGroupBox());
292
293 QVBoxLayout * groupBoxesLayout = new QVBoxLayout;
294 groupBoxesLayout->addWidget(createControlPointGroupBox());
295 groupBoxesLayout->addStretch();
296 groupBoxesLayout->addLayout(measureLayout);
297
298 QWidget * groupBoxesWidget = new QWidget;
299 groupBoxesWidget->setLayout(groupBoxesLayout);
300
302
303 QSplitter * topSplitter = new QSplitter;
304 topSplitter->addWidget(groupBoxesWidget);
305 topSplitter->addWidget(m_templateEditorWidget);
306// topSplitter->setStretchFactor(0, 4);
307// topSplitter->setStretchFactor(1, 3);
308
310
311 return topSplitter;
312 }
313
314
321
322 // create left vertical layout
323 m_ptIdValue = new QLabel;
324
325 m_numMeasures = new QLabel;
326
327 m_aprioriLatitude = new QLabel;
328 m_aprioriLongitude = new QLabel;
329 m_aprioriRadius = new QLabel;
330
331 // create right vertical layout's top layout
332 m_lockPoint = new QCheckBox("Edit Lock Point");
333 connect(m_lockPoint, SIGNAL(clicked(bool)), this, SLOT(setLockPoint(bool)));
334 m_ignorePoint = new QCheckBox("Ignore Point");
335 connect(m_ignorePoint, SIGNAL(clicked(bool)),
336 this, SLOT(setIgnorePoint(bool)));
337 connect(this, SIGNAL(ignorePointChanged()), m_ignorePoint, SLOT(toggle()));
338
340 for (int i=0; i<ControlPoint::PointTypeCount; i++) {
343 }
344 QFormLayout *pointTypeLayout = new QFormLayout;
345 pointTypeLayout->addRow("PointType:", m_pointTypeCombo);
346 connect(m_pointTypeCombo, SIGNAL(activated(int)),
347 this, SLOT(setPointType(int)));
348
351 connect(m_groundSourceCombo, SIGNAL(currentIndexChanged(int)),
352 this, SLOT(groundSourceFileSelectionChanged(int)));
353 QFormLayout *groundSourceLayout = new QFormLayout;
354 groundSourceLayout->addRow("Ground Source:", m_groundSourceCombo);
355 QFormLayout *radiusSourceLayout = new QFormLayout;
356 radiusSourceLayout->addRow("Radius Source:", m_radiusSourceCombo);
357
358 QVBoxLayout * mainLayout = new QVBoxLayout;
359 mainLayout->addWidget(m_ptIdValue);
360 mainLayout->addWidget(m_numMeasures);
361 mainLayout->addLayout(groundSourceLayout);
362 mainLayout->addLayout(radiusSourceLayout);
363 mainLayout->addWidget(m_aprioriLatitude);
364 mainLayout->addWidget(m_aprioriLongitude);
365 mainLayout->addWidget(m_aprioriRadius);
366 mainLayout->addWidget(m_lockPoint);
367 mainLayout->addWidget(m_ignorePoint);
368 mainLayout->addLayout(pointTypeLayout);
369
370 // create the groupbox
371 QGroupBox * groupBox = new QGroupBox("Control Point");
372 groupBox->setLayout(mainLayout);
373
374 return groupBox;
375 }
376
377
384
386 m_leftCombo->view()->installEventFilter(this);
387 m_leftCombo->setToolTip("Choose left control measure");
388 m_leftCombo->setWhatsThis("Choose left control measure identified by "
389 "cube filename.");
390 connect(m_leftCombo, SIGNAL(activated(int)),
391 this, SLOT(selectLeftMeasure(int)));
392 m_lockLeftMeasure = new QCheckBox("Edit Lock Measure");
393 connect(m_lockLeftMeasure, SIGNAL(clicked(bool)),
394 this, SLOT(setLockLeftMeasure(bool)));
395 m_ignoreLeftMeasure = new QCheckBox("Ignore Measure");
396 connect(m_ignoreLeftMeasure, SIGNAL(clicked(bool)),
397 this, SLOT(setIgnoreLeftMeasure(bool)));
398 connect(this, SIGNAL(ignoreLeftChanged()),
399 m_ignoreLeftMeasure, SLOT(toggle()));
400 m_leftReference = new QLabel();
401 m_leftMeasureType = new QLabel();
402 QVBoxLayout * leftLayout = new QVBoxLayout;
403 leftLayout->addWidget(m_leftCombo);
404 leftLayout->addWidget(m_lockLeftMeasure);
405 leftLayout->addWidget(m_ignoreLeftMeasure);
406 leftLayout->addWidget(m_leftReference);
407 leftLayout->addWidget(m_leftMeasureType);
408
409 QGroupBox * leftGroupBox = new QGroupBox("Left Measure");
410 leftGroupBox->setLayout(leftLayout);
411
412 return leftGroupBox;
413 }
414
415
426
427 // create widgets for the right groupbox
429 m_model = new QStandardItemModel();
430 m_rightCombo->setModel(m_model);
431 m_rightCombo->view()->installEventFilter(this);
432 m_rightCombo->setToolTip("Choose right control measure. "
433 "<strong>Shortcuts: PageUp/PageDown</strong>");
434 m_rightCombo->setWhatsThis("Choose right control measure identified by "
435 "cube filename. "
436 "Note: PageUp selects previous measure; "
437 "PageDown selects next meausure.");
438
439 m_rightCombo->view()->setSelectionMode(QAbstractItemView::SingleSelection);
440 m_rightCombo->view()->setDragEnabled(true);
441 m_rightCombo->view()->setAcceptDrops(true);
442 m_rightCombo->view()->setDropIndicatorShown(true);
443 m_rightCombo->view()->setDragDropMode(QAbstractItemView::InternalMove);
444
445 // Attach shortcuts to this widget for selecting right measures
446 // Note: Qt handles this memory for us since ControlPointEditWidget is the parent of these shortcuts
447 QShortcut *nextMeasure = new QShortcut(Qt::Key_PageDown, this);
448 connect(nextMeasure, SIGNAL(activated()), this, SLOT(nextRightMeasure()));
449 QShortcut *prevMeasure = new QShortcut(Qt::Key_PageUp, this);
450 connect(prevMeasure, SIGNAL(activated()), this, SLOT(previousRightMeasure()));
451
452 connect(m_rightCombo, SIGNAL(activated(int)),
453 this, SLOT(selectRightMeasure(int)));
454 m_lockRightMeasure = new QCheckBox("Edit Lock Measure");
455 connect(m_lockRightMeasure, SIGNAL(clicked(bool)),
456 this, SLOT(setLockRightMeasure(bool)));
457 m_ignoreRightMeasure = new QCheckBox("Ignore Measure");
458 connect(m_ignoreRightMeasure, SIGNAL(clicked(bool)),
459 this, SLOT(setIgnoreRightMeasure(bool)));
460 connect(this, SIGNAL(ignoreRightChanged()),
461 m_ignoreRightMeasure, SLOT(toggle()));
462 m_rightReference = new QLabel();
463 m_rightMeasureType = new QLabel();
464
465 // create right groupbox
466 QVBoxLayout * rightLayout = new QVBoxLayout;
467 rightLayout->addWidget(m_rightCombo);
468 rightLayout->addWidget(m_lockRightMeasure);
469 rightLayout->addWidget(m_ignoreRightMeasure);
470 rightLayout->addWidget(m_rightReference);
471 rightLayout->addWidget(m_rightMeasureType);
472
473 QGroupBox * rightGroupBox = new QGroupBox("Right Measure");
474 rightGroupBox->setLayout(rightLayout);
475
476 return rightGroupBox;
477 }
478
479
484
485 QToolBar *toolBar = new QToolBar("Template Editor ToolBar");
486
487 toolBar->addAction(m_openTemplateFile);
488 toolBar->addSeparator();
489 toolBar->addAction(m_saveTemplateFile);
490 toolBar->addAction(m_saveTemplateFileAs);
491
492 m_templateEditor = new QTextEdit;
493 connect(m_templateEditor, SIGNAL(textChanged()), this,
494 SLOT(setTemplateModified()));
495
496 QVBoxLayout *mainLayout = new QVBoxLayout;
497 mainLayout->addWidget(toolBar);
498 mainLayout->addWidget(m_templateEditor);
499
501 m_templateEditorWidget->setLayout(mainLayout);
502 }
503
504
509
510 m_closePointEditor = new QAction(QIcon(FileName("base/icons/fileclose.png").expanded()),
511 "&Close", this);
512 m_closePointEditor->setToolTip("Close this window");
513 m_closePointEditor->setStatusTip("Close this window");
514 m_closePointEditor->setShortcut(Qt::ALT + Qt::Key_F4);
515 QString whatsThis = "<b>Function:</b> Closes the Match Tool window for this point "
516 "<p><b>Shortcut:</b> Alt+F4 </p>";
517 m_closePointEditor->setWhatsThis(whatsThis);
518 connect(m_closePointEditor, SIGNAL(triggered()), this, SLOT(close()));
519
520 m_showHideTemplateEditor = new QAction(QIcon(FileName("base/icons/view_text.png").expanded()),
521 "&View/edit registration template", this);
522 m_showHideTemplateEditor->setCheckable(true);
523 m_showHideTemplateEditor->setToolTip("View and/or edit the registration template");
524 m_showHideTemplateEditor->setStatusTip("View and/or edit the registration template");
525 whatsThis = "<b>Function:</b> Displays the curent registration template. "
526 "The user may edit and save changes under a chosen filename.";
527 m_showHideTemplateEditor->setWhatsThis(whatsThis);
528 connect(m_showHideTemplateEditor, SIGNAL(triggered()), this,
529 SLOT(showHideTemplateEditor()));
530
531 m_saveChips = new QAction(QIcon(FileName("base/icons/window_new.png").expanded()),
532 "Save registration chips", this);
533 m_saveChips->setToolTip("Save registration chips");
534 m_saveChips->setStatusTip("Save registration chips");
535 whatsThis = "<b>Function:</b> Save registration chips to file. "
536 "Each chip: pattern, search, fit will be saved to a separate file.";
537 m_saveChips->setWhatsThis(whatsThis);
538 connect(m_saveChips, SIGNAL(triggered()), this, SLOT(saveChips()));
539
540 m_openTemplateFile = new QAction(QIcon(FileName("base/icons/fileopen.png").expanded()),
541 "&Open registration template", this);
542 m_openTemplateFile->setToolTip("Set registration template");
543 m_openTemplateFile->setStatusTip("Set registration template");
544 whatsThis = "<b>Function:</b> Allows user to select a new file to set as "
545 "the registration template";
546 m_openTemplateFile->setWhatsThis(whatsThis);
547 connect(m_openTemplateFile, SIGNAL(triggered()), this, SLOT(openTemplateFile()));
548
549 m_saveTemplateFile = new QAction(QIcon(FileName("base/icons/mActionFileSave.png").expanded()),
550 "&Save template file", this);
551 m_saveTemplateFile->setToolTip("Save the template file");
552 m_saveTemplateFile->setStatusTip("Save the template file");
553 m_saveTemplateFile->setWhatsThis("Save the registration template file");
554 connect(m_saveTemplateFile, SIGNAL(triggered()), this,
555 SLOT(saveTemplateFile()));
556
557 m_saveTemplateFileAs = new QAction(QIcon(FileName("base/icons/mActionFileSaveAs.png").expanded()),
558 "&Save template as...", this);
559 m_saveTemplateFileAs->setToolTip("Save the template file as");
560 m_saveTemplateFileAs->setStatusTip("Save the template file as");
561 m_saveTemplateFileAs->setWhatsThis("Save the registration template file as");
562 connect(m_saveTemplateFileAs, SIGNAL(triggered()), this,
563 SLOT(saveTemplateFileAs()));
564 }
565
566
581 void ControlPointEditWidget::setShapesForPoint(double latitude, double longitude) {
582
583 if (latitude == Null || longitude == Null) {
584 // Use current editPoint to get latitude, longitude.
585 // Use apriori surface point to find location on ground source. If
586 // apriori surface point does not exist use reference measure
587 if (m_editPoint->HasAprioriCoordinates()) {
588 SurfacePoint sPt = m_editPoint->GetAprioriSurfacePoint();
589 latitude = sPt.GetLatitude().degrees();
590 longitude = sPt.GetLongitude().degrees();
591 }
592 else {
593 ControlMeasure m = *(m_editPoint->GetRefMeasure());
594 int camIndex = m_serialNumberList->serialNumberIndex(m.GetCubeSerialNumber());
595 Camera *cam;
596 cam = m_controlNet->Camera(camIndex);
597 cam->SetImage(m.GetSample(),m.GetLine());
598 latitude = cam->UniversalLatitude();
599 longitude = cam->UniversalLongitude();
600 }
601 }
602
604 m_projectShapeNames.clear();
605 m_nameToShapeMap.clear();
606
607 // Get all shapes from project, putting shapes that contain the current m_editPoint at the
608 // top of the list.
609 QStringList shapeNamesNoPoint;
610 // Create map between the Shape file name & Shape
611 QList<ShapeList *> shapeLists = m_directory->project()->shapes();
612 foreach (ShapeList *shapeList, shapeLists) {
613 foreach (Shape *shape, *shapeList) {
614 UniversalGroundMap *gmap = new UniversalGroundMap(*(shape->cube()));
615 if (gmap->SetUniversalGround(latitude, longitude)) {
617 }
618 else {
619 shapeNamesNoPoint<<shape->fileName();
620 }
621 m_nameToShapeMap[shape->fileName()] = shape;
622 delete gmap;
623 }
624 }
626 // Add shapes that do not contain point
627 if (shapeNamesNoPoint.count() > 0) {
628 m_projectShapeNames<<shapeNamesNoPoint;
629 }
630 }
631
632
640 m_measureEditor->setLeftMeasure(m_leftMeasure, m_leftCube.data(), m_editPoint->GetId());
641 m_measureEditor->setRightMeasure(m_rightMeasure, m_rightCube.data(), m_editPoint->GetId());
642 }
643
644
651
652 // TODO If network & snList already exists do some error checking
653 // Make copy; we add ground source files to the list, and we don't want to cause problems for
654 // other ipce entities that are using
655// if (m_serialNumberList) {
656// delete m_serialNumberList;
657// m_serialNumberList = NULL;
658// }
659// m_serialNumberList = new SerialNumberList(snList);
660 m_serialNumberList = snList;
661 }
662
663
672 // TODO more error checking
673 m_control = control;
674 m_controlNet = control->controlNet();
675 m_cnetFileName = control->fileName();
676
677 QStringList cnetDirs = m_cnetFileName.split('/');
678 QString strippedCnetFilename = cnetDirs.value(cnetDirs.length() -1);
679 m_cnetFileNameLabel->setText("Control Network: " + strippedCnetFilename);
681 m_cnetFileNameLabel->setWhatsThis(m_cnetFileName);
682 setWindowTitle("Control Point Editor- Control Network File: " + m_cnetFileName);
683
684 emit newControlNetwork(m_controlNet);
685 }
686
687
695
696 if (m_directory->project()->activeControl()) {
697 m_control = m_directory->project()->activeControl();
698 m_controlNet = m_control->controlNet();
699 m_cnetFileName = m_control->fileName();
700
701 m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
702 setWindowTitle("Control Point Editor- Control Network File: " + m_cnetFileName);
703
704 emit newControlNetwork(m_controlNet);
705 }
706 }
707
708
721
723 if (groundMeasure) {
724 m_editPoint->Add(groundMeasure);
725
726 // Add to measure combo boxes
727 QString groundFile = m_serialNumberList->fileName(groundMeasure->GetCubeSerialNumber());
728 QString tempFileName = FileName(groundFile).name();
729
730 m_pointFiles<<groundFile;
731 m_leftCombo->addItem(tempFileName);
732 m_rightCombo->addItem(tempFileName);
733 int rightIndex = m_rightCombo->findText(tempFileName);
734 m_rightCombo->setCurrentIndex(rightIndex);
735 selectRightMeasure(rightIndex);
737 }
738 }
739
740
754
755 ControlMeasure *groundMeasure = NULL;
756
757 // Try to set ground source file information. If unsuccessful, return null ground measure
758 if (!setGroundSourceInfo()) {
759 return groundMeasure;
760 }
761
762 // Use apriori surface point to find location on ground source. If
763 // apriori surface point does not exist use reference measure
764 double lat = 0.;
765 double lon = 0.;
766 if (m_editPoint->HasAprioriCoordinates()) {
767 SurfacePoint sPt = m_editPoint->GetAprioriSurfacePoint();
768 lat = sPt.GetLatitude().degrees();
769 lon = sPt.GetLongitude().degrees();
770 }
771 else {
772 ControlMeasure m = *(m_editPoint->GetRefMeasure());
773 int camIndex = m_serialNumberList->serialNumberIndex(m.GetCubeSerialNumber());
774 Camera *cam;
775 cam = m_controlNet->Camera(camIndex);
776 cam->SetImage(m.GetSample(),m.GetLine());
777 lat = cam->UniversalLatitude();
778 lon = cam->UniversalLongitude();
779 }
780
781 // Try to locate point position on current ground source,
782 if (!m_groundGmap->SetUniversalGround(lat,lon)) {
783 QString message = "This point does not exist on the ground source.\n";
784 message += "Latitude = " + QString::number(lat);
785 message += " Longitude = " + QString::number(lon);
786 message += "\n A ground measure will not be created.";
787 QMessageBox::warning(this, "Warning", message);
788 }
789 else {
790 groundMeasure = new ControlMeasure;
791 groundMeasure->SetCubeSerialNumber(m_groundSN);
792 groundMeasure->SetType(ControlMeasure::Candidate);
793 groundMeasure->SetCoordinate(m_groundGmap->Sample(), m_groundGmap->Line());
794 groundMeasure->SetChooserName("GroundMeasureTemporary");
795 }
796
797 return groundMeasure;
798 }
799
800
811
812 FileName groundFile;
813 ControlPoint::SurfacePointSource::Source groundSourceType =
814 ControlPoint::SurfacePointSource::None;
815
816 bool success = false;
817
818 // No ground source chosen, clear out any old info
819 if (m_groundSourceCombo->currentText().contains("NONE")) {
820 success = false;
821 }
822 else {
823 // Chosen ground source is an imported shape in project
824 if (m_groundSourceCombo->currentText().contains(".ecub")) {
825 Shape *shape = m_nameToShapeMap[m_groundSourceCombo->currentText()];
826 groundFile = FileName(shape->fileName());
827 //groundSourceType = shape->surfacePointSource();
828 success = true;
829 }
830 // Not imported shape, must be from m_editPoints AprioriXYZSource in the cnet
831 else if (m_editPoint->HasAprioriSurfacePointSourceFile()) {
832 groundFile = FileName(m_groundSourceCombo->currentText());
833 // Apriori ground source does not exist and user chose not to give new location so simply
834 // return unsuccessful
835 if (!groundFile.fileExists()) {
836 success = false;
837 }
838 else {
839 groundSourceType = m_editPoint->GetAprioriSurfacePointSource();
840 success = true;
841 }
842 }
843 }
844
845 // If a new ground file was found set ground source information for later use, first clearing
846 // out the old ground source information. If new ground same as old ground, we will not change
847 // anything, simply return successful.
848 if (success && (groundFile.expanded() != m_groundFilename)) {
850 m_groundFilename = groundFile.expanded();
851
852 // Get cube, then universal groundmap
853 QScopedPointer<Cube> groundCube(new Cube(groundFile, "r"));
854 m_groundGmap.reset(NULL);
855 QScopedPointer<UniversalGroundMap> newGroundGmap(new UniversalGroundMap(*groundCube));
856 m_groundGmap.reset(newGroundGmap.take());
857
858 // Create new serial number for ground source and add to serial number list
859 m_groundSN = SerialNumber::Compose(groundFile.expanded(), true);
861
862 m_groundSourceType = groundSourceType;
863 }
864 // Could not successfully find a ground source file, clear out any old info and return
865 // unsuccessful
866 else if (!success) {
868 }
869
870 return success;
871 }
872
873
885
886 FileName newGroundFile;
887
888 if (!groundFile.fileExists()) {
889
890 // If user previously chose to change all ground source locations, but didn't update the net
891 // fix this ground source to new location
892 // If all groundLocations are to be changed...
894 QFileInfo oldFile(groundFile.expanded());
895 QFileInfo newFile(m_newGroundDir, oldFile.fileName());
896
897 newGroundFile = FileName(newFile.absoluteFilePath());
898 }
899
900 // If can't find ground, re-prompt user for new location. Maybe it's a new ground source.
901 if (!newGroundFile.fileExists()) {
902 // Give options for finding ground source file location. A new location
903 // for new location or new source, either a Shape in the project, or import a new shape,
904 // or simplay choose file?
905 QString message = "Ground Source file " + groundFile.expanded();
906 message += " doesn't exist. Has the file moved? Would you like to enter a new location for"
907 " this ground source?";
908 int ret = QMessageBox::question(this, "Ground Source not found", message);
909 if (ret == QMessageBox::Yes) {
910 QString dir = m_directory->project()->shapeDataRoot();
912 "New Ground Source Location", dir);
913 if (dialog->exec() == QDialog::Accepted) {
914 m_newGroundDir = dialog->selectedFiles().value(0);
917 // Change all ground source locations to reflect new directory
920 }
921 // Change location of apriori for current edit point so combo boxes updated properly
922 QFileInfo oldFile(groundFile.expanded());
923 QFileInfo newFile(m_newGroundDir, oldFile.fileName());
924 newGroundFile = newFile.absoluteFilePath();
925 m_editPoint->SetAprioriSurfacePointSourceFile(newGroundFile.toString());
926 }
927 else {
928 // Either user does not want to change location of ground source or the new location
929 // Dialog was cancelled. Load point without the ground source.
930 newGroundFile = NULL;
931 }
932 }
933 else {
934 // Either user does not want to change location of ground source or the new location
935 // Dialog was cancelled. Load point without the ground source.
936 newGroundFile = NULL;
937 }
938 }
939 }
940 return newGroundFile;
941 }
942
943
950
951 for (int i = 0; i < m_controlNet->GetNumPoints(); i++ ) {
952 ControlPoint *cp = m_controlNet->GetPoint(i);
954 FileName groundFile(cp->GetAprioriSurfacePointSourceFile());
955 QFileInfo oldFile(groundFile.expanded());
956 QFileInfo newFile(m_newGroundDir, oldFile.fileName());
957 groundFile = newFile.absoluteFilePath();
959 }
960 }
961 emit cnetModified();
962 }
963
964
972
973 //Get the reference image's shape model
974 QString referenceSN = m_editPoint->GetReferenceSN();
975 QString referenceFileName = m_serialNumberList->fileName(referenceSN);
976 QScopedPointer<Cube> referenceCube(new Cube(referenceFileName, "r"));
977 PvlGroup kernels = referenceCube->group("Kernels");
978 QString shapeFile = kernels["ShapeModel"];
979
980 // If the reference measure has a shape model cube then set that as the radius
981 // This will NOT WORK for shape model files (not the default of Null or Ellipsoid)
982 // that are not cubes
983 if (shapeFile.contains(".cub")) {
984 if (shapeFile.contains("dem")) {
985 m_radiusSourceType = ControlPoint::RadiusSource::DEM;
986 }
987 else {
988 m_radiusSourceType = ControlPoint::RadiusSource::Ellipsoid;
989 }
990
991 m_radiusFilename = shapeFile;
992 initDem(shapeFile);
993 }
994 // If no shape model then use the ABC of the target body
995 else {
996 m_radiusSourceType = ControlPoint::RadiusSource::Ellipsoid;
997 Spice *refSpice = new Spice(*referenceCube);
998 Distance refRadii[3];
999 refSpice->radii(refRadii);
1000 m_demFile = QString::number(refRadii[0].meters()) + ", " +
1001 QString::number(refRadii[1].meters()) + ", " +
1002 QString::number(refRadii[2].meters());
1003
1004 m_radiusFilename = "";
1005 }
1006 }
1007
1008
1016 void ControlPointEditWidget::initDem (QString demFile) {
1017
1018 // If a DEM is already opened, check if new is same as old. If new,
1019 // close old, open new.
1020 if (m_demOpen) {
1021 if (m_demFile == demFile) {
1022 return;
1023 }
1024
1025 m_demCube.reset(NULL);
1026 m_demFile.clear();
1027 }
1028
1029 QApplication::setOverrideCursor(Qt::WaitCursor);
1030 try {
1031 QScopedPointer<Cube> newDemCube(new Cube(demFile, "r"));
1032
1033 m_demFile = FileName(newDemCube->fileName()).name();
1034 m_demCube.reset(newDemCube.take());
1035 }
1036 catch (IException &e) {
1037 QMessageBox::critical(this, "Error", e.toString());
1038 QApplication::restoreOverrideCursor();
1039 return;
1040 }
1041 m_demOpen = true;
1042
1043 // Make sure this is a dem
1044 if (!m_demCube->hasTable("ShapeModelStatistics")) {
1045 QString message = m_demFile + " is not a DEM.";
1046 QMessageBox::critical(this, "Error", message);
1047 m_demCube.reset(NULL);
1048 m_demOpen = false;
1049 m_demFile.clear();
1050 QApplication::restoreOverrideCursor();
1051 return;
1052 }
1053 m_radiusSourceType = ControlPoint::RadiusSource::DEM;
1054 m_radiusFilename = demFile;
1055
1056 QApplication::restoreOverrideCursor();
1057 }
1058
1059
1067 double ControlPointEditWidget::demRadius(double latitude, double longitude) {
1068
1069 if (!m_demOpen) return Null;
1070
1071 UniversalGroundMap *demMap = new UniversalGroundMap(*m_demCube);
1072 if (!demMap->SetUniversalGround(latitude, longitude)) {
1073 delete demMap;
1074 demMap = NULL;
1075 return Null;
1076 }
1077
1078 // Use bilinear interpolation to read radius from DEM
1079 // Use bilinear interpolation from dem
1080 Interpolator *interp = new Interpolator(Interpolator::BiLinearType);
1081
1082 // Buffer used to read from the model
1083 Portal *portal = new Portal(interp->Samples(), interp->Lines(),
1084 m_demCube->pixelType(),
1085 interp->HotSample(), interp->HotLine());
1086 portal->SetPosition(demMap->Sample(), demMap->Line(), 1);
1087 m_demCube->read(*portal);
1088 double radius = interp->Interpolate(demMap->Sample(), demMap->Line(),
1089 portal->DoubleBuffer());
1090 delete demMap;
1091 demMap = NULL;
1092 delete interp;
1093 interp = NULL;
1094 delete portal;
1095 portal = NULL;
1096
1097 return radius;
1098 }
1099
1100
1108
1109 QString newChosenGroundFile = m_groundSourceCombo->currentText();
1110 if (newChosenGroundFile == m_groundFilename) {
1111 return;
1112 }
1114 }
1115
1116
1122
1123 if (m_groundSN.isEmpty()) {
1124 return;
1125 }
1126
1127 // If the loaded point is a fixed point, see if there is a temporary measure
1128 // holding the coordinate information for the current ground source. If so,
1129 // delete this measure and remove from the Chip viewport and measure selection combo.
1130 if (m_editPoint && m_editPoint->GetType() != ControlPoint::Free &&
1131 m_editPoint->HasSerialNumber(m_groundSN)) {
1132 m_editPoint->Delete(m_groundSN);
1133
1134 if (m_leftCombo->findText(QFileInfo(m_groundFilename).fileName()) >= 0) {
1135 m_leftCombo->removeItem(m_leftCombo->findText(QFileInfo(m_groundFilename).fileName()));
1136 if (m_leftMeasure->GetCubeSerialNumber() == m_groundSN) {
1138 }
1139 }
1140 if (m_rightCombo->findText(QFileInfo(m_groundFilename).fileName())) {
1141 m_rightCombo->removeItem(m_rightCombo->findText(QFileInfo(m_groundFilename).fileName()));
1142 if (m_rightMeasure->GetCubeSerialNumber() == m_groundSN) {
1144 }
1145 }
1146 m_pointFiles.removeAll(m_groundFilename);
1147 }
1148 // Remove from serial number list
1150
1151 // Reset ground source variables
1152 m_groundFilename.clear();
1153 m_groundSN.clear();
1154 m_groundGmap.reset(NULL);
1155 m_groundSourceType = ControlPoint::SurfacePointSource::None;
1156 }
1157
1158
1166 void ControlPointEditWidget::setEditPoint(ControlPoint *controlPoint, QString serialNumber) {
1167
1168 // If m_editPoint was never saved to control net (parent=NULL), delete
1169 if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1170 delete m_editPoint;
1171 m_editPoint = NULL;
1172 }
1173
1174 // If incoming control point is new point (has not been saved to control net, simply assign
1175 // to m_editPoint, otherwise create copy. It will not be saved to net until "Save Point"
1176 // is selected
1177 if (controlPoint->Parent() == NULL) {
1178 m_editPoint = controlPoint;
1179
1180 // New point in editor, so colorize all save buttons
1181 colorizeAllSaveButtons("red");
1182 }
1183 else {
1185 *m_editPoint = *controlPoint;
1186
1187 // New point loaded, make sure all save button's text is default black color
1188 colorizeAllSaveButtons("black");
1189 }
1190 loadPoint(serialNumber);
1191 loadTemplateFile(m_measureEditor->templateFileName());
1192 }
1193
1194
1195 void ControlPointEditWidget::colorizeAllSaveButtons(QString color) {
1196
1197 if (color == "black") {
1198 // Don't need to colorize save measure button, when loading new measure, the measure editor
1199 // will set back to default palette.
1200 m_savePoint->setPalette(m_saveDefaultPalette);
1201 m_saveNet->setPalette(m_saveDefaultPalette);
1202 }
1203 else if (color == "red") {
1204 m_measureEditor->colorizeSaveButton();
1207 }
1208 }
1209
1210
1231 void ControlPointEditWidget::loadPoint(QString serialNumber) {
1232
1233 // Write pointId
1234 QString CPId = m_editPoint->GetId();
1235
1236 QString ptId("Point ID: ");
1237 ptId += (QString) CPId;
1238 m_ptIdValue->setText(ptId);
1239
1240 // Set shapes for this point. Shapes are what has been imported into project.
1242
1243 // Write number of measures
1244 QString ptsize = "Number of Measures: " +
1245 QString::number(m_editPoint->GetNumMeasures());
1246 m_numMeasures->setText(ptsize);
1247
1248 // Set EditLock box correctly
1249 m_lockPoint->setChecked(m_editPoint->IsEditLocked());
1250
1251 // Set ignore box correctly
1252 m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1253
1254
1255 // Refill combos since they are dependent on the current edit point
1256 // Turn off signals until filled since we don't want slot called.
1257 m_groundSourceCombo->blockSignals(true);
1258 m_radiusSourceCombo->blockSignals(true);
1259 m_groundSourceCombo->clear();
1260 m_radiusSourceCombo->clear();
1261 m_groundSourceCombo->addItem("NONE");
1262 m_groundSourceCombo->setCurrentText("NONE");
1263 m_radiusSourceCombo->addItem("NONE - Use reference measure's radius");
1264 m_radiusSourceCombo->setCurrentText("NONE - Use reference measure's radius");
1265
1266 // Load any imported project shapes that contain m_editPoint into the ground and any Dem's into
1267 // radius source combo boxes. Only add Dems to radius combo.
1268 if (m_projectShapeNames.count() > 0) {
1269 for (int i=0; i<m_numberProjectShapesWithPoint; i++) {
1271 if (shape->radiusSource() == ControlPoint::RadiusSource::DEM) {
1272 m_radiusSourceCombo->addItem(shape->fileName());
1273 }
1274 else {
1275 m_groundSourceCombo->addItem(shape->fileName());
1276 }
1277 }
1278 }
1279
1280 // If available, add the CP AprioriSurfacePointSourceFile and AprioriRadiusSourceFile
1281 if (m_editPoint->HasAprioriSurfacePointSourceFile()) {
1282 FileName aprioriSurfacePointFile = FileName(m_editPoint->GetAprioriSurfacePointSourceFile());
1283 // If file doesn't exist, prompt user for changing location before adding to combo
1284 if (!aprioriSurfacePointFile.fileExists()) {
1285 aprioriSurfacePointFile = checkGroundFileLocation(aprioriSurfacePointFile);
1286 }
1287 if (!aprioriSurfacePointFile.toString().isEmpty()) {
1288 m_groundSourceCombo->addItem(aprioriSurfacePointFile.toString());
1289 m_groundSourceCombo->setCurrentText(aprioriSurfacePointFile.toString());
1290 m_groundSourceCombo->setItemData(m_groundSourceCombo->currentIndex(),
1291 QColor(Qt::darkGreen), Qt::ForegroundRole);
1292 m_groundSourceCombo->setItemData(m_groundSourceCombo->currentIndex(),
1293 QFont("DejaVu Sans", 10, QFont::Bold), Qt::FontRole);
1294 }
1295 }
1296
1297 if (m_editPoint->HasAprioriRadiusSourceFile()) {
1298 //TODO check location of radius file
1299 m_radiusSourceCombo->addItem(m_editPoint->GetAprioriRadiusSourceFile());
1300 m_radiusSourceCombo->setCurrentText(m_editPoint->GetAprioriRadiusSourceFile());
1301 m_radiusSourceCombo->setItemData(m_radiusSourceCombo->currentIndex(),
1302 QColor(Qt::green), Qt::ForegroundRole);
1303 m_radiusSourceCombo->setItemData(m_groundSourceCombo->currentIndex(),
1304 QFont("DejaVu Sans", 10, QFont::Bold), Qt::FontRole);
1305 }
1306 if (m_editPoint->GetType() == ControlPoint::Free) {
1307 m_groundSourceCombo->setEnabled(false);
1308 m_radiusSourceCombo->setEnabled(false);
1309 }
1310 else {
1311 m_groundSourceCombo->setEnabled(true);
1312 m_radiusSourceCombo->setEnabled(true);
1313 }
1314 m_groundSourceCombo->blockSignals(false);
1315 m_radiusSourceCombo->blockSignals(false);
1316
1317
1318 // If constrained or fixed point, create a measure for
1319 // the ground source, load reference on left, ground source on right
1320 if (m_editPoint->GetType() != ControlPoint::Free) {
1321 // If m_editPoint already has a ground measure, delete
1322 for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1323 ControlMeasure &m = *(*m_editPoint)[i];
1324 if (m.GetChooserName() == "GroundMeasureTemporary") {
1325 m_editPoint->Delete(&m);
1326 }
1327 }
1328 // Create a temporary measure to hold the ground point info for ground source
1329 // This measure will be deleted when the ControlPoint is saved to the
1330 // ControlNet.
1332 if (groundMeasure) {
1333 m_editPoint->Add(groundMeasure);
1334 }
1335 }
1336
1337
1338
1339 // Reset PointType combo box appropriately.
1340 m_pointTypeCombo->clear();
1341 for (int i=0; i<ControlPoint::PointTypeCount; i++) {
1344 }
1346 m_pointTypeCombo->setToolTip("Change ControlPoint type");
1347
1349
1350
1351
1352 // Clear combo boxes
1353 m_leftCombo->clear();
1354 m_rightCombo->clear();
1355 m_pointFiles.clear();
1356
1357
1358 // Need all files for this point
1359 for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1360 ControlMeasure &m = *(*m_editPoint)[i];
1361 QString file = m_serialNumberList->fileName(m.GetCubeSerialNumber());
1362 m_pointFiles<<file;
1363 QString tempFileName = FileName(file).name();
1364
1365 // This actually fills the right combo box for selecting measures. A model was used to enable
1366 // drag & drop for ordering measures which will also set the blink order.
1367 QStandardItem *item = new QStandardItem(tempFileName);
1368 item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled);
1369 m_model->appendRow(item);
1370
1371 m_leftCombo->addItem(tempFileName);
1372
1373 if (m_editPoint->IsReferenceExplicit() &&
1374 (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
1375 m_leftCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1376 m_rightCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1377 }
1378 }
1379
1381
1382 int leftIndex = -1;
1383 int rightIndex = -1;
1384
1385 QString referenceSerialNumber;
1386 // Check for reference
1387 if (m_editPoint->IsReferenceExplicit()) {
1388 referenceSerialNumber = m_editPoint->GetReferenceSN();
1389 leftIndex = m_editPoint->IndexOfRefMeasure();
1390 }
1391
1392 if (!serialNumber.isEmpty() && serialNumber != referenceSerialNumber) {
1393 QString file = m_serialNumberList->fileName(serialNumber);
1394 rightIndex = m_rightCombo->findText(FileName(file).name());
1395 if (leftIndex == -1) {
1396 if (rightIndex == 0) {
1397 leftIndex = 1;
1398 }
1399 else {
1400 leftIndex = 0;
1401 }
1402 }
1403 }
1404
1405 if (leftIndex == -1) {
1406 if (rightIndex == 0) {
1407 leftIndex = 1;
1408 }
1409 else {
1410 leftIndex = 0;
1411 }
1412 }
1413
1414 // If ground measure exists, load in right viewport
1415 if (m_editPoint->HasSerialNumber(m_groundSN)) {
1416 rightIndex = m_rightCombo->findText(m_groundSN);
1417 }
1418 if (rightIndex <= 0) {
1419 if (leftIndex == 0) {
1420 rightIndex = 1;
1421 }
1422 else {
1423 rightIndex = 0;
1424 }
1425 }
1426 // Handle pts with a single measure, for now simply put measure on left/right
1427 // Evenutally put on left with black on right??
1428 if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0;
1429
1430 m_rightCombo->setCurrentIndex(rightIndex);
1431 m_leftCombo->setCurrentIndex(leftIndex);
1432
1433 // Initialize pointEditor with measures
1434 selectLeftMeasure(leftIndex);
1435 selectRightMeasure(rightIndex);
1436
1437 this->setVisible(true);
1438 this->raise();
1439 }
1440
1441
1451
1452 void ControlPointEditWidget::createControlPoint(double latitude, double longitude, Cube *cube,
1453 bool isGroundSource) {
1454
1455 // TODO: CHECK SUBPIXEL REGISTER RADIO BUTTON OPTION (CHECKBOX?)
1456
1457 // Create list box of all files highlighting those that
1458 // contain the point.
1459 QStringList pointFiles;
1460
1461 Camera *cam;
1462 for (int i = 0; i < m_serialNumberList->size(); i++) {
1463 if (m_serialNumberList->serialNumber(i) == m_groundSN) continue;
1464 cam = m_controlNet->Camera(i);
1465 if (cam->SetUniversalGround(latitude, longitude)) {
1466 // Make sure point is within image boundary
1467 double samp = cam->Sample();
1468 double line = cam->Line();
1469 if (samp >= 1 && samp <= cam->Samples() &&
1470 line >= 1 && line <= cam->Lines()) {
1471 pointFiles<<m_serialNumberList->fileName(i);
1472 }
1473 }
1474 }
1475
1476 // Set shapes from project to fill dialog, indicating number of shapes that contain the CP.
1477 // The shapes which contain the CP will be at the front of the QStringList.
1478 setShapesForPoint(latitude, longitude);
1479
1481 m_serialNumberList, m_lastUsedPointId, this, true, true, true);
1482 newPointDialog->setFiles(pointFiles);
1483 newPointDialog->setGroundSource(m_projectShapeNames, m_numberProjectShapesWithPoint);
1484
1485 // Load imported project shapes that are Dems and contain point location into the radius combo.
1486 if (m_projectShapeNames.count() > 0) {
1487 QStringList radiusSourceFiles;
1488 for (int i=0; i<m_numberProjectShapesWithPoint; i++) {
1490 if (shape->radiusSource() == ControlPoint::RadiusSource::DEM) {
1491 radiusSourceFiles<<shape->fileName();
1492 }
1493 }
1494 newPointDialog->setRadiusSource(radiusSourceFiles);
1495 }
1496
1497
1498
1499 if (newPointDialog->exec() == QDialog::Accepted) {
1500 m_lastUsedPointId = newPointDialog->pointId();
1501 ControlPoint *newPoint =
1503
1504 // If this ControlPointId already exists, message box pops up and user is
1505 // asked to enter a new value.
1506 if (m_controlNet->ContainsPoint(newPoint->GetId())) {
1507 QString message = "A ControlPoint with Point Id = [" + newPoint->GetId();
1508 message += "] already exists. Re-enter Point Id for this ControlPoint.";
1509 QMessageBox::warning(this, "New Point Id", message);
1510 pointFiles.clear();
1511 delete newPoint;
1512 newPoint = NULL;
1513 createControlPoint(latitude, longitude);
1514 return;
1515 }
1516
1518
1519 QStringList selectedFiles = newPointDialog->selectedFiles();
1520 foreach (QString selectedFile, selectedFiles) {
1521 // Create measure for any file selected
1523 // Find serial number for this file
1524 QString sn = m_serialNumberList->serialNumber(selectedFile);
1525 m->SetCubeSerialNumber(sn);
1526 int camIndex = m_serialNumberList->fileNameIndex(selectedFile);
1527 cam = m_controlNet->Camera(camIndex);
1528 cam->SetUniversalGround(latitude, longitude);
1529 m->SetCoordinate(cam->Sample(),cam->Line());
1530 m->SetAprioriSample(cam->Sample());
1531 m->SetAprioriLine(cam->Line());
1534 m->SetCamera(cam);
1535 newPoint->Add(m);
1536 }
1537
1538 // Get point type from dialog
1539 bool isGroundPoint = (newPointDialog->pointType() != ControlPoint::Free);
1540 newPoint->SetType((ControlPoint::PointType) newPointDialog->pointType());
1541
1542 if (isGroundPoint) {
1543 Shape *shape = m_nameToShapeMap[newPointDialog->groundSource()];
1544 // Save ground source information in control point
1545 if (shape) {
1546 newPoint->SetAprioriSurfacePointSource(shape->surfacePointSource());
1547 }
1548 else {
1549 newPoint->SetAprioriSurfacePointSource(ControlPoint::SurfacePointSource::None);
1550 }
1552 }
1553
1554 setEditPoint(newPoint);
1555 emit controlPointAdded(newPoint->GetId());
1556 }
1557 }
1558
1559
1566
1567 // Make a copy and make sure editPoint is a copy (which means it does not
1568 // have a parent network.
1569 if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1570 delete m_editPoint;
1571 m_editPoint = NULL;
1572 }
1574 *m_editPoint = *controlPoint;
1575 loadPoint();
1576
1577 DeleteControlPointDialog *deletePointDialog = new DeleteControlPointDialog;
1578 QString CPId = m_editPoint->GetId();
1579 deletePointDialog->pointIdValue->setText(CPId);
1580
1581 // Need all files for this point
1582 for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1583 ControlMeasure &m = *(*m_editPoint)[i];
1584 QString file = m_serialNumberList->fileName(m.GetCubeSerialNumber());
1585 deletePointDialog->fileList->addItem(file);
1586 }
1587
1588 if (deletePointDialog->exec()) {
1589
1590 int numDeleted = deletePointDialog->fileList->selectedItems().count();
1591
1592 // Delete entire control point, either through deleteAllCheckBox or all measures selected
1593 if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1594 numDeleted == m_editPoint->GetNumMeasures()) {
1595
1596 // If all measures being deleted, let user know and give them the option to quit operation
1597 if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1598 QString message = "You have selected all measures in this point to be deleted. This "
1599 "control point will be deleted. Do you want to delete this control point?";
1600 int response = QMessageBox::question(this,
1601 "Delete control point", message,
1602 QMessageBox::Yes | QMessageBox::No,
1603 QMessageBox::Yes);
1604 // If No, do nothing
1605 if (response == QMessageBox::No) {
1606 return;
1607 }
1608 }
1609
1610 //this->setVisible(false);
1611 // remove this point from the control network
1612 if (m_controlNet->DeletePoint(m_editPoint->GetId()) ==
1614 QMessageBox::information(this, "EditLocked Point",
1615 "This point is EditLocked and cannot be deleted.");
1616 return;
1617 }
1618 if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1619// delete m_editPoint;
1620// m_editPoint = NULL;
1621 }
1622 }
1623
1624 // Delete specific measures from control point
1625 else {
1626 // Keep track of editLocked measures for reporting
1627 int lockedMeasures = 0;
1628 for (int i=0; i<deletePointDialog->fileList->count(); i++) {
1629 QListWidgetItem *item = deletePointDialog->fileList->item(i);
1630 if (!item->isSelected()) continue;
1631
1632 // Do not delete reference without asking user
1633 if (m_editPoint->IsReferenceExplicit() &&
1634 (m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
1635 (*m_editPoint)[i]->GetCubeSerialNumber())) {
1636 QString message = "You are trying to delete the Reference measure."
1637 " Do you really want to delete the Reference measure?";
1638 switch (QMessageBox::question(this,
1639 "Delete Reference measure?", message,
1640 "&Yes", "&No", 0, 0)) {
1641 // Yes: skip to end of switch todelete the measure
1642 case 0:
1643 break;
1644 // No: continue to next measure in the loop
1645 case 1:
1646 // if only a single measure and it's reference and user chooses not to delete,
1647 // simply return. The point has not changed.
1648 if (numDeleted == 1) {
1649 return;
1650 }
1651 continue;
1652 }
1653 }
1654
1655 if (m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1656 lockedMeasures++;
1657 }
1658 }
1659
1660 if (lockedMeasures > 0) {
1661 QMessageBox::information(this,"EditLocked Measures",
1662 QString::number(lockedMeasures) + " / "
1663 + QString::number(
1664 deletePointDialog->fileList->selectedItems().size()) +
1665 " measures are EditLocked and were not deleted.");
1666 }
1667
1668 loadPoint();
1669
1670// loadTemplateFile(m_pointEditor->templateFileName());
1671 }
1672
1673 // emit a signal to alert user to save when exiting
1674 m_control->setModified(true);
1675 emit cnetModified();
1676
1677 if (m_editPoint != NULL) {
1678 // Change Save Point button text to red
1680 }
1681 }
1682 }
1683
1684
1748
1749 // Read original measures from the network for comparison with measures
1750 // that have been edited
1751 ControlMeasure *origLeftMeasure =
1752 m_editPoint->GetMeasure(m_leftMeasure->GetCubeSerialNumber());
1753 ControlMeasure *origRightMeasure =
1754 m_editPoint->GetMeasure(m_rightMeasure->GetCubeSerialNumber());
1755 // Neither measure has changed, return
1756 if (*origLeftMeasure == *m_leftMeasure && *origRightMeasure == *m_rightMeasure) {
1757 return;
1758 }
1759
1760 if (m_editPoint->IsIgnored()) {
1761 QString message = "You are saving changes to a measure on an ignored ";
1762 message += "point. Do you want to set Ignore = False on the point and ";
1763 message += "both measures?";
1764 switch (QMessageBox::question(this, "Save Measure", message, "&Yes", "&No", 0, 0)) {
1765 // Yes: set Ignore=false for the point and measures and save point
1766 case 0:
1767 m_editPoint->SetIgnored(false);
1768 emit ignorePointChanged();
1769 if (m_leftMeasure->IsIgnored()) {
1770 m_leftMeasure->SetIgnored(false);
1771 emit ignoreLeftChanged();
1772 }
1773 if (m_rightMeasure->IsIgnored()) {
1774 m_rightMeasure->SetIgnored(false);
1775 emit ignoreRightChanged();
1776 }
1777 // No: keep Ignore=true and save measure
1778 case 1:
1779 break;
1780 }
1781 }
1782
1783 bool savedAMeasure = false;
1784 // Error check both measures for edit lock, ignore status and reference
1785 bool leftChangeOk = validateMeasureChange(m_leftMeasure);
1786 if (leftChangeOk) {
1787 m_leftMeasure->SetChooserName(Application::UserName());
1788 *origLeftMeasure = *m_leftMeasure;
1789 savedAMeasure = true;
1790 }
1791 bool rightChangeOk = validateMeasureChange(m_rightMeasure);
1792 if (rightChangeOk) {
1793 m_rightMeasure->SetChooserName(Application::UserName());
1794 *origRightMeasure = *m_rightMeasure;
1795 savedAMeasure = true;
1796 }
1797
1798 // If this is a fixed or constrained point, and either the left or right measure is the ground
1799 // source, update the lat,lon,radius.
1800 //
1801 if (m_editPoint->GetType() != ControlPoint::Free &&
1802 (m_leftMeasure->GetCubeSerialNumber() == m_groundSN ||
1803 m_rightMeasure->GetCubeSerialNumber() == m_groundSN)) {
1804 // If point is locked and it is not a new point, print error
1805 if (m_editPoint->IsEditLocked() && m_controlNet->ContainsPoint(m_editPoint->GetId())) {
1806 QString message = "This control point is edit locked. The Apriori latitude, longitude and ";
1807 message += "radius cannot be updated. You must first unlock the point by clicking the ";
1808 message += "check box above labeled \"Edit Lock Point\".";
1809 QMessageBox::warning(this, "Point Locked", message);
1810 return;
1811 }
1812 if (m_leftMeasure->IsIgnored()) {
1813 QString message = "This is a Constrained or Fixed point and the reference measure is ";
1814 message += "Ignored. Unset the Ignore flag on the reference measure before saving.";
1815 QMessageBox::warning(this, "Point Locked", message);
1816 return;
1817 }
1818 updateGroundPosition();
1819 }
1820
1821 // If left measure == right measure, update left
1822 if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
1824 // Update left measure of measureEditor
1825 m_measureEditor->setLeftMeasure (m_leftMeasure, m_leftCube.data(),
1826 m_editPoint->GetId());
1827 }
1828
1829 // Change Save Point button text to red
1830 if (savedAMeasure) {
1832 }
1833
1834 // Update measure info
1837 }
1838
1839
1848
1849 // Read original measures from the network for comparison with measures
1850 // that have been edited
1851 ControlMeasure *origMeasure =
1852 m_editPoint->GetMeasure(m->GetCubeSerialNumber());
1853
1854 // If measure hasn't changed, return false, to keep original
1855 if (*m == *origMeasure) return false;
1856
1857 // Is measure on Left or Right? This is needed to print correct information
1858 // to users in identifying the measure and for updating information widgets.
1859 QString side = "right";
1860 if (m->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1861 side = "left";
1862 }
1863
1864 // Only print error if both original measure in network and the current
1865 // edit measure are both editLocked and measure has changed. If only the edit measure is
1866 // locked, then user just locked and it needs to be saved.
1867 // Do not use this classes IsMeasureLocked since we actually want to
1868 // check the original againsted the edit measure and we don't care
1869 // if this is a reference measure. The check for moving a reference is
1870 // done below.
1871 if (origMeasure->IsEditLocked() && m->IsEditLocked()) {
1872 QString message = "The " + side + " measure is editLocked ";
1873 message += "for editing. Do you want to set EditLock = False for this ";
1874 message += "measure?";
1875 int response = QMessageBox::question(this, "Save Measure",
1876 message, QMessageBox::Yes | QMessageBox::No);
1877 // Yes: set EditLock=false for the right measure
1878 if (response == QMessageBox::Yes) {
1879 m->SetEditLock(false);
1880 if (side == "left") {
1881 m_lockLeftMeasure->setChecked(false);
1882 }
1883 else {
1884 m_lockRightMeasure->setChecked(false);
1885 }
1886 }
1887 // No: keep EditLock=true and do NOT save measure
1888 else {
1889 return false;
1890 }
1891 }
1892
1893 if (origMeasure->IsIgnored() && m->IsIgnored()) {
1894 QString message = "The " + side + "measure is ignored. ";
1895 message += "Do you want to set Ignore = False on the measure?";
1896 switch (QMessageBox::question(this, "Save Measure", message, "&Yes", "&No", 0, 0)) {
1897 // Yes: set Ignore=false for the right measure and save point
1898 case 0:
1899 m->SetIgnored(false);
1900 if (side == "left") {
1901 emit ignoreLeftChanged();
1902 }
1903 else {
1904 emit ignoreRightChanged();
1905 }
1906 // No: keep Ignore=true and save point
1907 case 1:
1908 break;;
1909 }
1910 }
1911
1912 // If measure is explicit reference and it has moved,warn user
1913 ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
1914 if (m_editPoint->IsReferenceExplicit()) {
1915 if (refMeasure->GetCubeSerialNumber() == m->GetCubeSerialNumber()) {
1916 if (m->GetSample() != origMeasure->GetSample() || m->GetLine() != origMeasure->GetLine()) {
1917 QString message = "You are making a change to the reference measure. You ";
1918 message += "may need to move all of the other measures to match the new ";
1919 message += " coordinate of the reference measure. Do you really want to ";
1920 message += " change the reference measure's location? ";
1921 switch(QMessageBox::question(this, "Save Measure",
1922 message, "&Yes", "&No", 0, 0)){
1923 // Yes: Save measure
1924 case 0:
1925 break;
1926 // No: keep original reference, return without saving
1927 case 1:
1928 ControlMeasure *origLeftMeasure =
1929 m_editPoint->GetMeasure(m_leftMeasure->GetCubeSerialNumber());
1930 m_measureEditor->setLeftPosition(origLeftMeasure->GetSample(),
1931 origLeftMeasure->GetLine());
1932 return false;
1933 }
1934 }
1935 }
1936 // New reference measure
1937 else if (side == "left" && (refMeasure->GetCubeSerialNumber() != m->GetCubeSerialNumber())) {
1938 QString message = "This point already contains a reference measure. ";
1939 message += "Would you like to replace it with the measure on the left?";
1940 int response = QMessageBox::question(this,
1941 "Save Measure", message,
1942 QMessageBox::Yes | QMessageBox::No,
1943 QMessageBox::Yes);
1944 // Replace reference measure
1945 if (response == QMessageBox::Yes) {
1946 // Update measure file combo boxes: old reference normal font,
1947 // new reference bold font
1948 QString file = m_serialNumberList->fileName(m_leftMeasure->GetCubeSerialNumber());
1949 QString fname = FileName(file).name();
1950 int iref = m_leftCombo->findText(fname);
1951
1952 // Save normal font from new reference measure
1953 QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
1954 m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1955 iref = m_rightCombo->findText(fname);
1956 m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1957
1958 file = m_serialNumberList->fileName(refMeasure->GetCubeSerialNumber());
1959 fname = FileName(file).name();
1960 iref = m_leftCombo->findText(fname);
1961 m_leftCombo->setItemData(iref,font,Qt::FontRole);
1962 iref = m_rightCombo->findText(fname);
1963 m_rightCombo->setItemData(iref,font,Qt::FontRole);
1964
1965 m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
1966 }
1967 }
1968 }
1969 else {
1970 // No explicit reference, If left, set explicit reference
1971 if (side == "left") {
1972 m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
1973 }
1974 }
1975
1976 // All test pass, return true (ok to change measure)
1977 return true;
1978
1979
1980 }
1981
1982
1993
1994 // Check if ControlPoint has reference measure, if reference Measure is
1995 // not the same measure that is on the left chip viewport, set left
1996 // measure as reference.
1997 ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
1998 if (refMeasure->GetCubeSerialNumber() != m_leftMeasure->GetCubeSerialNumber()) {
1999 QString message = "This point already contains a reference measure. ";
2000 message += "Would you like to replace it with the measure on the left?";
2001 int response = QMessageBox::question(this,
2002 "Match Tool Save Measure", message,
2003 QMessageBox::Yes | QMessageBox::No,
2004 QMessageBox::Yes);
2005 // Replace reference measure
2006 if (response == QMessageBox::Yes) {
2007 // Update measure file combo boxes: old reference normal font,
2008 // new reference bold font
2009 QString file = m_serialNumberList->fileName(m_leftMeasure->GetCubeSerialNumber());
2010 QString fname = FileName(file).name();
2011 int iref = m_leftCombo->findText(fname);
2012
2013 // Save normal font from new reference measure
2014 QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
2015 m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2016 iref = m_rightCombo->findText(fname);
2017 m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2018
2019 file = m_serialNumberList->fileName(refMeasure->GetCubeSerialNumber());
2020 fname = FileName(file).name();
2021 iref = m_leftCombo->findText(fname);
2022 m_leftCombo->setItemData(iref,font,Qt::FontRole);
2023 iref = m_rightCombo->findText(fname);
2024 m_rightCombo->setItemData(iref,font,Qt::FontRole);
2025
2026 m_editPoint->SetRefMeasure(m_leftMeasure->GetCubeSerialNumber());
2027 }
2028
2029 // ??? Need to set rest of measures to Candiate and add more warning. ???//
2030 }
2031 }
2032
2033
2034 /*
2035 * Update the position of ground point
2036 *
2037 * @author 2012-04-26 Tracie Sucharski - moved functionality from measureSaved
2038 *
2039 * @internal
2040 *
2041 */
2042 void ControlPointEditWidget::updateGroundPosition() {
2043
2044 // Determine if the left or right measure is the ground. Use ground measure to update
2045 // apriori surface point.
2046 ControlMeasure *groundMeasure;
2047 if (m_leftMeasure->GetCubeSerialNumber() == m_groundSN) {
2048 groundMeasure = m_leftMeasure;
2049 }
2050 else {
2051 groundMeasure = m_rightMeasure;
2052 }
2053 m_groundGmap->SetImage(groundMeasure->GetSample(), groundMeasure->GetLine());
2054
2055 double lat = m_groundGmap->UniversalLatitude();
2056 double lon = m_groundGmap->UniversalLongitude();
2057
2058 // Find radius source file
2059 // If nothing has been selected from the Radius source combo, use the Reference measure
2060 if (m_radiusSourceCombo->currentText().contains("NONE")) {
2061 m_radiusFilename.clear();
2062 m_demOpen = false;
2063 m_demFile.clear();
2064 m_demCube.reset(NULL);
2066 }
2067 else {
2068 Shape *shape = m_nameToShapeMap[m_radiusSourceCombo->currentText()];
2069 if (shape) {
2070 m_radiusFilename = shape->cube()->externalCubeFileName().toString();
2071 //m_radiusSourceType = shape->radiusSource();
2072 }
2073 // Radius source comes from what is already saved in the cnet as AprioriRadiusSourceFile
2074 // This will contain the path
2075 else {
2076 m_radiusFilename = m_radiusSourceCombo->currentText();
2077 m_radiusSourceType = m_editPoint->GetAprioriRadiusSource();
2078 }
2079 initDem(m_radiusFilename);
2080 }
2081
2082
2083 double radius;
2084 // Update radius, order of precedence
2085 // 1. If a dem has been opened, read radius from dem.
2086 // 2. Get radius from reference measure
2087 // If image has shape model, radius will come from shape model
2088 //
2089 if (m_demOpen) {
2090 radius = demRadius(lat,lon);
2091 if (radius == Null) {
2092 QString msg = "Could not read radius from DEM, will default to "
2093 "local radius of reference measure.";
2094 QMessageBox::warning(this, "Warning", msg);
2095 if (m_editPoint->GetRefMeasure()->Camera()->SetGround(Latitude(lat, Angle::Degrees),
2096 Longitude(lon, Angle::Degrees))) {
2097 radius = m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
2098 // TODO Should this be set here, this is probably not working as intended since it is
2099 // overwritten below outside of if (radius == Null)
2100 m_editPoint->SetAprioriRadiusSource(ControlPoint::RadiusSource::None);
2101 }
2102 else {
2103 QString message = "Error trying to get radius at this pt. "
2104 "Lat/Lon does not fall on the reference measure. "
2105 "Cannot save this measure.";
2106 QMessageBox::critical(this,"Error",message);
2107 return;
2108 }
2109 }
2110 m_editPoint->SetAprioriRadiusSource(m_radiusSourceType);
2111 m_editPoint->SetAprioriRadiusSourceFile(m_radiusFilename);
2112 }
2113 else {
2114 // Get radius from reference image
2115 if (m_editPoint->GetRefMeasure()->Camera()->SetGround(Latitude(lat, Angle::Degrees),
2116 Longitude(lon, Angle::Degrees))) {
2117 radius = m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
2118 }
2119 else {
2120 QString message = "Error trying to get radius at this pt. "
2121 "Lat/Lon does not fall on the reference measure. "
2122 "Cannot save this measure.";
2123 QMessageBox::critical(this,"Error",message);
2124 return;
2125 }
2126 }
2127
2128 try {
2129 // Read apriori surface point if it exists so that point is
2130 // replaced, but sigmas are retained. Save sigmas because the
2131 // SurfacePoint class will change them if the coordinates change.
2132 if (m_editPoint->HasAprioriCoordinates()) {
2133 SurfacePoint aprioriPt = m_editPoint->GetAprioriSurfacePoint();
2134 Distance latSigma = aprioriPt.GetLatSigmaDistance();
2135 Distance lonSigma = aprioriPt.GetLonSigmaDistance();
2136 Distance radiusSigma = aprioriPt.GetLocalRadiusSigma();
2137 aprioriPt.SetSphericalCoordinates(Latitude(lat, Angle::Degrees),
2138 Longitude(lon, Angle::Degrees),
2139 Distance(radius, Distance::Meters));
2140 aprioriPt.SetSphericalSigmasDistance(latSigma, lonSigma, radiusSigma);
2141 m_editPoint->SetAprioriSurfacePoint(aprioriPt);
2142 }
2143 else {
2144 m_editPoint->SetAprioriSurfacePoint(SurfacePoint(
2145 Latitude(lat, Angle::Degrees),
2146 Longitude(lon, Angle::Degrees),
2147 Distance(radius, Distance::Meters)));
2148 }
2149 }
2150 catch (IException &e) {
2151 QString message = "Unable to set Apriori Surface Point.\n";
2152 message += "Latitude = " + QString::number(lat);
2153 message += " Longitude = " + QString::number(lon);
2154 message += " Radius = " + QString::number(radius) + "\n";
2155 message += e.toString();
2156 QMessageBox::critical(this,"Error",message);
2157 return;
2158 }
2159
2160 m_editPoint->SetAprioriSurfacePointSource(m_groundSourceType);
2161 QString fullGroundFilename;
2162 if (m_groundFilename.contains(".ecub")) {
2163 // Find shape to get external cube filename
2164 fullGroundFilename = m_nameToShapeMap[m_groundFilename]->cube()->externalCubeFileName().expanded();
2165 }
2166 else {
2167 fullGroundFilename = m_groundFilename;
2168 }
2169 m_editPoint->SetAprioriSurfacePointSourceFile(fullGroundFilename);
2170
2172 }
2173
2174
2190
2191 // Make a copy of edit point for updating the control net since the edit
2192 // point is still loaded in the point editor.
2193 ControlPoint *updatePoint = new ControlPoint;
2194 *updatePoint = *m_editPoint;
2195
2196 // If this is a fixed or constrained point, see if there is a temporary
2197 // measure holding the coordinate information from the ground source.
2198 // If so, delete this measure before saving point. Clear out the
2199 // fixed Measure variable (memory deleted in ControlPoint::Delete).
2200 if (updatePoint->GetType() != ControlPoint::Free && updatePoint->HasSerialNumber(m_groundSN)) {
2201 // Delete measure with m_groundSN
2202 updatePoint->Delete(m_groundSN);
2203 }
2204
2205 // If edit point exists in the network, save the updated point. If it
2206 // does not exist, add it.
2207 if (m_controlNet->ContainsPoint(updatePoint->GetId())) {
2208 ControlPoint *p;
2209 p = m_controlNet->GetPoint(QString(updatePoint->GetId()));
2210 *p = *updatePoint;
2211 delete updatePoint;
2212 updatePoint = NULL;
2213 emit controlPointChanged(m_editPoint->GetId());
2214 }
2215 else {
2216 m_controlNet->AddPoint(updatePoint);
2217 emit controlPointAdded(m_editPoint->GetId());
2218 }
2219
2220 // Change Save Measure button text back to default
2221 m_savePoint->setPalette(m_saveDefaultPalette);
2222
2223 // At exit, or when opening new net, use for prompting user for a save
2224 m_cnetModified = true;
2225 m_control->setModified(true);
2226 emit cnetModified();
2227 // Refresh chipViewports to show new positions of controlPoints
2228 m_measureEditor->refreshChips();
2229 }
2230
2231
2248
2249 if (m_editPoint == NULL) return;
2250
2251 // If pointType is equal to current type, nothing to do
2252 if (m_editPoint->GetType() == pointType) return;
2253 int oldType = m_editPoint->GetType();
2254
2255 // Error check ignored and locked status
2256 if (pointType != ControlPoint::Free && m_leftMeasure->IsIgnored()) {
2257 m_pointTypeCombo->setCurrentIndex((int) m_editPoint->GetType());
2258 QString message = "The reference measure is Ignored. Unset the Ignore flag on the ";
2259 message += "reference measure before setting the point type to Constrained or Fixed.";
2260 QMessageBox::warning(m_parent, "Ignored Reference Measure", message);
2261 return;
2262 }
2263 ControlPoint::Status status = m_editPoint->SetType((ControlPoint::PointType) pointType);
2264 if (status == ControlPoint::PointLocked) {
2265 m_pointTypeCombo->setCurrentIndex((int) m_editPoint->GetType());
2266 QString message = "This control point is edit locked. The point type cannot be changed. You ";
2267 message += "must first unlock the point by clicking the check box above labeled ";
2268 message += "\"Edit Lock Point\".";
2269 QMessageBox::warning(m_parent, "Point Locked", message);
2270 return;
2271 }
2272
2273 // Changing type between Contrained and Fixed, simply colorize Save CP button and return. Do
2274 // not re-load CP or re-create ground CM.
2275 if (oldType != ControlPoint::Free && m_editPoint->GetType() != ControlPoint::Free) {
2277 }
2278 // If changing from Constrained or Fixed to Free, remove ground CM, disable ground/radius source
2279 // combos, re-load CP, colorize Save CP.
2280 else if (oldType != ControlPoint::Free && m_editPoint->GetType() == ControlPoint::Free) {
2281 // Find temporary measure holding the coordinate information from the ground source and
2282 // delete from CP. This CM has a chooser name = GroundMeasureTemporary.
2283 // Clear out the fixed Measure variable (memory deleted in ControlPoint::Delete).
2284 for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
2285 ControlMeasure &m = *(*m_editPoint)[i];
2286 if (m.GetChooserName() == "GroundMeasureTemporary") {
2287 m_editPoint->Delete(&m);
2288 }
2289 }
2290 loadPoint();
2291 m_groundSourceCombo->setEnabled(false);
2292 m_radiusSourceCombo->setEnabled(false);
2294 }
2295 // Changing from Free to Constrained or Fixed, loadGroundMeasure,which will create temporary
2296 // gound measure, load into the measure combo boxes and colorize Save CP button.
2297 else if (oldType == ControlPoint::Free && m_editPoint->GetType() != ControlPoint::Free) {
2299 m_groundSourceCombo->setEnabled(true);
2300 m_radiusSourceCombo->setEnabled(true);
2302 }
2303 }
2304
2305
2316
2317 if (m_editPoint == NULL) return;
2318
2319 m_editPoint->SetEditLock(lock);
2321 }
2322
2323
2335
2336 if (m_editPoint == NULL) return;
2337
2338 ControlPoint::Status status = m_editPoint->SetIgnored(ignore);
2339 if (status == ControlPoint::PointLocked) {
2340 m_ignorePoint->setChecked(m_editPoint->IsIgnored());
2341 QString message = "Unable to change Ignored on point. Set EditLock ";
2342 message += " to False.";
2343 QMessageBox::critical(this, "Error", message);
2344 return;
2345 }
2347 }
2348
2349
2365
2366 if (m_editPoint->IsEditLocked()) {
2367 m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
2368 QMessageBox::warning(this, "Point Locked","Point is Edit Locked. You must un-lock point"
2369 " before changing a measure.");
2370 m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
2371 return;
2372 }
2373
2374 if (m_leftMeasure != NULL) m_leftMeasure->SetEditLock(lock);
2375
2376 // If the right chip is the same as the left chip , update the right editLock
2377 // box.
2378 if (m_rightMeasure != NULL) {
2379 if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
2380 m_rightMeasure->SetEditLock(lock);
2381 m_lockRightMeasure->setChecked(lock);
2382 }
2383 }
2384 emit measureChanged();
2385 }
2386
2387
2405
2406 if (m_leftMeasure != NULL) m_leftMeasure->SetIgnored(ignore);
2407
2408 // If the right chip is the same as the left chip , update the right
2409 // ignore box.
2410 if (m_rightMeasure != NULL) {
2411 if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
2412 m_rightMeasure->SetIgnored(ignore);
2413 m_ignoreRightMeasure->setChecked(ignore);
2414 }
2415 }
2416 emit measureChanged();
2417 }
2418
2419
2435
2436 if (m_editPoint->IsEditLocked()) {
2437 m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
2438 QMessageBox::warning(this, "Point Locked","Point is Edit Locked. You must un-lock point"
2439 " before changing a measure.");
2440 m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
2441 return;
2442 }
2443
2444 if (m_rightMeasure != NULL) m_rightMeasure->SetEditLock(lock);
2445
2446 // If the left chip is the same as the right chip , update the left editLock box.
2447 if (m_leftMeasure != NULL) {
2448 if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
2449 m_leftMeasure->SetEditLock(lock);
2450 m_lockLeftMeasure->setChecked(lock);
2451 }
2452 }
2453 emit measureChanged();
2454 }
2455
2456
2475
2476 if (m_rightMeasure != NULL) m_rightMeasure->SetIgnored(ignore);
2477
2478 // If the right chip is the same as the left chip , update the right
2479 // ignore blox.
2480 if (m_leftMeasure != NULL) {
2481 if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
2482 m_leftMeasure->SetIgnored(ignore);
2483 m_ignoreLeftMeasure->setChecked(ignore);
2484 }
2485 }
2486 emit measureChanged();
2487 }
2488
2489
2500
2501 int curIndex = m_rightCombo->currentIndex();
2502 if (curIndex < m_rightCombo->count() - 1) {
2503 // update the right measure list index and select that measure
2504 m_rightCombo->setCurrentIndex(curIndex + 1);
2505 selectRightMeasure(curIndex+1);
2506 }
2507 }
2508
2509
2520
2521 int curIndex = m_rightCombo->currentIndex();
2522 if (curIndex > 0) {
2523 // update the right measure list index and select that measure
2524 m_rightCombo->setCurrentIndex(curIndex - 1);
2525 selectRightMeasure(curIndex-1);
2526 }
2527 }
2528
2529
2530
2544
2545 QString file = m_pointFiles[index];
2546 QString serial;
2547 try {
2548 serial = m_serialNumberList->serialNumber(file);
2549 }
2550 catch (IException &e) {
2551 QString message = "Make sure the correct cube is opened.\n\n";
2552 message += e.toString();
2553 QMessageBox::critical(this, "Error", message);
2554
2555 // Set index of combo back to what it was before user selected new. Find the index
2556 // of current left measure.
2557 QString file = m_serialNumberList->fileName(m_leftMeasure->GetCubeSerialNumber());
2558 int i = m_leftCombo->findText(FileName(file).name());
2559 if (i < 0) i = 0;
2560 m_leftCombo->setCurrentIndex(i);
2561 return;
2562 }
2563
2564 if (m_leftMeasure != NULL) {
2565 delete m_leftMeasure;
2566 m_leftMeasure = NULL;
2567 }
2568
2570 *m_leftMeasure = *((*m_editPoint)[serial]);
2571
2572 // If m_leftCube is not null, delete before creating new one
2573 m_leftCube.reset(new Cube(file, "r"));
2574
2575 // Update left measure of pointEditor
2576 m_measureEditor->setLeftMeasure (m_leftMeasure, m_leftCube.data(), m_editPoint->GetId());
2578 }
2579
2580
2592
2593 QString file = m_pointFiles[index];
2594
2595 QString serial;
2596 try {
2597 serial = m_serialNumberList->serialNumber(file);
2598 }
2599 catch (IException &e) {
2600 QString message = "Make sure the correct cube is opened.\n\n";
2601 message += e.toString();
2602 QMessageBox::critical(this, "Error", message);
2603
2604 // Set index of combo back to what it was before user selected new. Find the index
2605 // of current left measure.
2606 QString file = m_serialNumberList->fileName(m_rightMeasure->GetCubeSerialNumber());
2607 int i = m_rightCombo->findText(FileName(file).name());
2608 if (i < 0) i = 0;
2609 m_rightCombo->setCurrentIndex(i);
2610 return;
2611 }
2612
2613 if (m_rightMeasure != NULL) {
2614 delete m_rightMeasure;
2615 m_rightMeasure = NULL;
2616 }
2617
2619 *m_rightMeasure = *((*m_editPoint)[serial]);
2620
2621 // If m_rightCube is not null, delete before creating new one
2622 m_rightCube.reset(new Cube(file, "r"));
2623
2624 // Update left measure of pointEditor
2625 m_measureEditor->setRightMeasure (m_rightMeasure, m_rightCube.data(), m_editPoint->GetId());
2627 }
2628
2629
2648
2649 // Set editLock measure box correctly
2651 m_leftMeasure->GetCubeSerialNumber()));
2652 // Set ignore measure box correctly
2653 m_ignoreLeftMeasure->setChecked(m_leftMeasure->IsIgnored());
2654
2655 QString s = "Reference: ";
2656 if (m_editPoint->IsReferenceExplicit() &&
2657 (QString(m_leftMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2658 s += "True";
2659 }
2660 else {
2661 s += "False";
2662 }
2663 m_leftReference->setText(s);
2664
2665 s = "Measure Type: ";
2666 if (m_leftMeasure->GetType() == ControlMeasure::Candidate) s += "Candidate";
2667 if (m_leftMeasure->GetType() == ControlMeasure::Manual) s += "Manual";
2668 if (m_leftMeasure->GetType() == ControlMeasure::RegisteredPixel) s += "RegisteredPixel";
2669 if (m_leftMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s += "RegisteredSubPixel";
2670 m_leftMeasureType->setText(s);
2671 }
2672
2673
2694
2695 // Set editLock measure box correctly
2697 m_rightMeasure->GetCubeSerialNumber()));
2698 // Set ignore measure box correctly
2699 m_ignoreRightMeasure->setChecked(m_rightMeasure->IsIgnored());
2700
2701 QString s = "Reference: ";
2702 if (m_editPoint->IsReferenceExplicit() &&
2703 (QString(m_rightMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2704 s += "True";
2705 }
2706 else {
2707 s += "False";
2708 }
2709
2710 m_rightReference->setText(s);
2711
2712 s = "Measure Type: ";
2713 if (m_rightMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2714 if (m_rightMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2715 if (m_rightMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2716 if (m_rightMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2717 m_rightMeasureType->setText(s);
2718 }
2719
2720
2721
2733
2734 if(e->type() != QEvent::Leave) return false;
2735 if(o == m_leftCombo->view()) {
2737 m_leftCombo->hidePopup();
2738 }
2739 if (o == m_rightCombo->view()) {
2741 m_rightCombo->hidePopup();
2742 }
2743 return true;
2744 }
2745
2746
2754
2755 if (m_templateModified) {
2756 int r = QMessageBox::warning(this, tr("OK to continue?"),
2757 tr("The currently opened registration template has been modified.\n"
2758 "Save changes?"),
2759 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2760 QMessageBox::Yes);
2761
2762 if (r == QMessageBox::Yes)
2764 else if (r == QMessageBox::Cancel)
2765 return false;
2766 }
2767
2768 return true;
2769 }
2770
2771
2778
2779 if (!okToContinue())
2780 return;
2781
2782 QString filename = QFileDialog::getOpenFileName(this,
2783 "Select a registration template", ".",
2784 "Registration template files (*.def *.pvl);;All files (*)");
2785
2786 if (filename.isEmpty())
2787 return;
2788
2789 if (m_measureEditor->setTemplateFile(filename)) {
2790 loadTemplateFile(filename);
2791 }
2792 }
2793
2794
2801
2802 QFile file(FileName((QString) fn).expanded());
2803 if (!file.open(QIODevice::ReadOnly)) {
2804 QString msg = "Failed to open template file \"" + fn + "\"";
2805 QMessageBox::warning(this, "IO Error", msg);
2806 return;
2807 }
2808
2809 QTextStream stream(&file);
2810 m_templateEditor->setText(stream.readAll());
2811 file.close();
2812
2813 QScrollBar * sb = m_templateEditor->verticalScrollBar();
2814 sb->setValue(sb->minimum());
2815
2816 m_templateModified = false;
2817 m_saveTemplateFile->setEnabled(false);
2818 }
2819
2820
2825
2826 m_templateModified = true;
2827 m_saveTemplateFile->setEnabled(true);
2828 }
2829
2830
2835
2836 if (!m_templateModified)
2837 return;
2838
2839 QString filename =
2840 m_measureEditor->templateFileName();
2841
2842 writeTemplateFile(filename);
2843 }
2844
2845
2850
2851 QString filename = QFileDialog::getSaveFileName(this,
2852 "Save registration template", ".",
2853 "Registration template files (*.def *.pvl);;All files (*)");
2854
2855 if (filename.isEmpty())
2856 return;
2857
2858 writeTemplateFile(filename);
2859 }
2860
2861
2868
2869 QString contents = m_templateEditor->toPlainText();
2870
2871 // catch errors in Pvl format when populating pvl object
2872 stringstream ss;
2873 ss << contents;
2874 try {
2875 Pvl pvl;
2876 ss >> pvl;
2877 }
2878 catch(IException &e) {
2879 QString message = e.toString();
2880 QMessageBox::warning(this, "Error", message);
2881 return;
2882 }
2883
2884 QString expandedFileName(FileName((QString) fn).expanded());
2885
2886 QFile file(expandedFileName);
2887
2888 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2889 QString msg = "Failed to save template file to \"" + fn + "\"\nDo you "
2890 "have permission?";
2891 QMessageBox::warning(this, "IO Error", msg);
2892 return;
2893 }
2894
2895 // now save contents
2896 QTextStream stream(&file);
2897 stream << contents;
2898 file.close();
2899
2900 if (m_measureEditor->setTemplateFile(fn)) {
2901 m_templateModified = false;
2902 m_saveTemplateFile->setEnabled(false);
2903 }
2904 }
2905
2906
2920
2921 try{
2922 // Get the template file from the ControlPointEditWidget object
2923 Pvl templatePvl(m_measureEditor->templateFileName());
2924 // Create registration dialog window using PvlEditDialog class
2925 // to view and/or edit the template
2926 PvlEditDialog registrationDialog(templatePvl);
2927 registrationDialog.setWindowTitle("View or Edit Template File: "
2928 + templatePvl.fileName());
2929 registrationDialog.resize(550,360);
2930 registrationDialog.exec();
2931 }
2932 catch (IException &e) {
2933 QString message = e.toString();
2934 QMessageBox::information(this, "Error", message);
2935 }
2936 }
2937
2938
2944
2946
2947 m_measureEditor->saveChips();
2948 }
2949
2950
2955
2957 return;
2958
2959 m_templateEditorWidget->setVisible(!m_templateEditorWidget->isVisible());
2960 }
2961
2962
2969 if(templateList->type() == "registrations") {
2970 for(int i = 0; i < templateList->size(); i++) {
2971 m_templateComboBox->addItem(templateList->at(i)->importName()
2972 + "/" + FileName(templateList->at(i)->fileName()).name());
2973 }
2974 }
2975 }
2976
2977
2986 QString expandedFileName = filename;
2987 if(!filename.startsWith("$base")){
2988 expandedFileName = m_directory->project()->templateRoot()
2989 + "/registrations/" + filename;
2990 }
2991 if (m_measureEditor->setTemplateFile(expandedFileName)) {
2992 loadTemplateFile(expandedFileName);
2993 }
2994 }
2995
2996
3004 if(fileName.startsWith("$base")) {
3005 m_templateComboBox->setCurrentIndex(0);
3006 }
3007 QList<QString> components = fileName.split("/");
3008 int size = components.size();
3009 int index = m_templateComboBox->findText(components[size - 2] + "/" + components[size - 1]);
3010 if (index != -1) {
3011 m_templateComboBox->setCurrentIndex(index);
3012 }
3013 }
3014
3015
3028
3029 QString s;
3030
3031 SurfacePoint aprioriPoint = m_editPoint->GetAprioriSurfacePoint();
3032 if (aprioriPoint.GetLatitude().degrees() == Null) {
3033 s = "Apriori Latitude: Null";
3034 }
3035 else {
3036 s = "Apriori Latitude: " +
3037 QString::number(aprioriPoint.GetLatitude().degrees());
3038 }
3039 m_aprioriLatitude->setText(s);
3040 if (aprioriPoint.GetLongitude().degrees() == Null) {
3041 s = "Apriori Longitude: Null";
3042 }
3043 else {
3044 s = "Apriori Longitude: " +
3045 QString::number(aprioriPoint.GetLongitude().degrees());
3046 }
3047 m_aprioriLongitude->setText(s);
3048 if (aprioriPoint.GetLocalRadius().meters() == Null) {
3049 s = "Apriori Radius: Null";
3050 }
3051 else {
3052 s = "Apriori Radius: " +
3053 QString::number(aprioriPoint.GetLocalRadius().meters(),'f',2) +
3054 " <meters>";
3055 }
3056 m_aprioriRadius->setText(s);
3057 }
3058
3059
3075// TODO Is this needed?
3076//
3077// void ControlPointEditWidget::refresh() {
3078//
3079// // Check point being edited, make sure it still exists, if not ???
3080// // Update ignored checkbox??
3081// if (m_editPoint != NULL) {
3082// try {
3083// QString id = m_ptIdValue->text().remove("Point ID: ");
3084// m_controlNet->GetPoint(id);
3085// }
3086// catch (IException &) {
3087// delete m_editPoint;
3088// m_editPoint = NULL;
3089// emit controlPointChanged();
3092// }
3093// }
3094// }
3095
3096
3103
3104 QColor qc = Qt::red;
3105 QPalette p = m_savePoint->palette();
3106 p.setColor(QPalette::ButtonText,qc);
3107 m_savePoint->setPalette(p);
3108 }
3109
3110
3120
3121 if (reset) {
3122 // Change Save Net button text back to default black
3123 m_saveNet->setPalette(m_saveDefaultPalette);
3124 }
3125 else {
3126 QColor qc = Qt::red;
3127 QPalette p = m_savePoint->palette();
3128 p.setColor(QPalette::ButtonText,qc);
3129 m_saveNet->setPalette(p);
3130 }
3131
3132 }
3133
3134
3146 bool ControlPointEditWidget::IsMeasureLocked (QString serialNumber) {
3147
3148 if (m_editPoint == NULL) return false;
3149
3150 // Reference implicitly editLocked
3151 if (m_editPoint->IsEditLocked() && m_editPoint->IsReferenceExplicit() &&
3152 (m_editPoint->GetReferenceSN() == serialNumber)) {
3153 return true;
3154 }
3155 // Return measures explicit editLocked value
3156 else {
3157 return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
3158 }
3159
3160 }
3161
3162
3171
3172 m_control->write();
3173
3174 // Change Save Measure button text back to default
3175 m_saveNet->setPalette(m_saveDefaultPalette);
3176 }
3177
3178
3183 delete m_editPoint;
3184 m_editPoint = NULL;
3185 }
3186
3187
3188 // 2014-07-21 TLS Ipce This needs to be changed to return the help information or
3189 // widget?? to the calling program, so that it can be added to a menu or toolbar.
3190#if 0
3191 void ControlPointEditWidget::showHelp() {
3192
3193 QDialog *helpDialog = new QDialog(this);
3194 helpDialog->setWindowTitle("Match Tool Help");
3195
3196 QVBoxLayout *mainLayout = new QVBoxLayout;
3197 helpDialog->setLayout(mainLayout);
3198
3199 QLabel *matchTitle = new QLabel("<h2>Match Tool</h2>");
3200 mainLayout->addWidget(matchTitle);
3201
3202 QLabel *matchSubtitle = new QLabel("A tool for interactively measuring and editing sample/line "
3203 "registration points between cubes. These "
3204 "points contain sample, line postions only, no latitude or "
3205 "longitude values are used or recorded.");
3206 matchSubtitle->setWordWrap(true);
3207 mainLayout->addWidget(matchSubtitle);
3208
3209 QTabWidget *tabArea = new QTabWidget;
3210 tabArea->setDocumentMode(true);
3211 mainLayout->addWidget(tabArea);
3212
3213 // TAB 1 - Overview
3214 QScrollArea *overviewTab = new QScrollArea;
3215 overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3216 overviewTab->setWidgetResizable(true);
3217 QWidget *overviewContainer = new QWidget;
3218 QVBoxLayout *overviewLayout = new QVBoxLayout;
3219 overviewContainer->setLayout(overviewLayout);
3220
3221 QLabel *purposeTitle = new QLabel("<h2>Purpose</h2>");
3222 overviewLayout->addWidget(purposeTitle);
3223
3224 QLabel *purposeText = new QLabel("<p>This tool is for recording and editing registration "
3225 "points measured between cubes displayed in the <i>qview</i> main window.</p> <p>The "
3226 "recorded registration points are sample and line pixel coordinates only. Therefore, this "
3227 "tool can be used on any images including ones that do not contain a camera model "
3228 "(i.e, The existence of the Isis Instrument Group on the image labels is not required). "
3229 "This also means that the tool differs from the <i>qnet</i> control point network "
3230 "application in that no latitude or longitude values are ever used or recorded "
3231 "(regardless if the image has a camera model in Isis).</p>"
3232 "<p>The output control point network that this tool generates is primarily used 1) as "
3233 "input for an image-wide sample/line translation to register one image to another by "
3234 "'moving' pixel locations - refer to the documentation for applications such as "
3235 "<i>translate</i> and <i>warp</i>, or 2) to export the file and use the recorded "
3236 "measurements in other spreadsheet or plotting packages to visualize magnitude "
3237 "and direction of varying translations of the images relative to one another.</p> "
3238 "<p>An automated version of this match tool is the <i>coreg</i> application. This tool "
3239 "can be used to visually evaluate and edit the control point network created by "
3240 "<i>coreg</i>.</p> "
3241 "<p>The format of the output point network file is binary. This tool uses the Isis control "
3242 " network framework to create, co-register and save all control points and pixel "
3243 "measurements. The application <i>cnetbin2pvl</i> can be used to convert from binary to "
3244 "a readable PVL format."
3245 "<p>The Mouse Button functions are: (same as <i>qnet</i>)<ul><li>Modify Point=Left</li> "
3246 "<li>Delete Point=Middle</li><li>Create New Point=Right</li></ul></p>"
3247 "<p>Control Points are drawn on the associated displayed cubes with the following colors: "
3248 "Green=Valid registration point; Yellow=Ignored point; Red=Active point being edited");
3249 purposeText->setWordWrap(true);
3250 overviewLayout->addWidget(purposeText);
3251
3252 overviewTab->setWidget(overviewContainer);
3253
3254 // TAB 2 - Quick Start
3255 QScrollArea *quickTab = new QScrollArea;
3256 quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3257 quickTab->setWidgetResizable(true);
3258 QWidget *quickContainer = new QWidget;
3259 QVBoxLayout *quickLayout = new QVBoxLayout;
3260 quickContainer->setLayout(quickLayout);
3261
3262 QLabel *quickTitle = new QLabel("<h2>Quick Start</h2>");
3263 quickLayout->addWidget(quickTitle);
3264
3265 QLabel *quickSubTitle = new QLabel("<h3>Preparation:</h3>");
3266 quickLayout->addWidget(quickSubTitle);
3267
3268 QString toolIconDir = FileName("$base/icons").expanded();
3269
3270 QLabel *quickPrep = new QLabel("<p><ul>"
3271 "<li>Open the cubes with overlapping areas for choosing control points</li>"
3272 "<li>Choose the match tool <img src=\"" + toolIconDir +
3273 "/stock_draw-connector-with-arrows.png\" width=22 height=22> "
3274 "from the toolpad on the right side of the <i>qview</i> main window</li>");
3275 quickPrep->setWordWrap(true);
3276 quickLayout->addWidget(quickPrep);
3277
3278 QLabel *morePrep = new QLabel("<p>Once the Match tool is activated the tool bar at the top "
3279 "of the main window contains file action buttons and a help button:");
3280 morePrep->setWordWrap(true);
3281 quickLayout->addWidget(morePrep);
3282
3283 QLabel *fileButtons = new QLabel("<p><ul>"
3284 "<li><img src=\"" + toolIconDir + "/fileopen.png\" width=22 height=22> Open an existing "
3285 "control network <b>Note:</b> If you do not open an existing network, a new one will "
3286 "be created</li>"
3287 "<li><img src=\"" + toolIconDir + "/mActionFileSaveAs.png\" width=22 height=22> Save "
3288 "control network as ...</li>"
3289 "<li><img src=\"" + toolIconDir + "/mActionFileSave.png\" width=22 height=22> Save "
3290 "control network to current file</li>"
3291 "<li><img src=\"" + toolIconDir + "/help-contents.png\" width=22 height=22> Show Help "
3292 "</li></ul></p>");
3293 fileButtons->setWordWrap(true);
3294 quickLayout->addWidget(fileButtons);
3295
3296 QLabel *quickFunctionTitle = new QLabel("<h3>Cube Viewport Functions:</h3>");
3297 quickLayout->addWidget(quickFunctionTitle);
3298
3299 QLabel *quickFunction = new QLabel(
3300 "The match tool window will be shown once "
3301 "you click in a cube viewport window using one of the following "
3302 "mouse functions. <b>Note:</b> Existing control points are drawn on the cube viewports");
3303 quickFunction->setWordWrap(true);
3304 quickLayout->addWidget(quickFunction);
3305
3306 QLabel *quickDesc = new QLabel("<p><ul>"
3307 "<li>Left Click - Modify the control point closest to the click <b>Note:</b> "
3308 "All cubes in the control point must be displayed before loading the point</li>"
3309 "<li>Middle Click - Delete the control point closest to the click</li>"
3310 "<li>Right Click - Create a new control point at the click location</li></ul></p>");
3311 quickDesc->setWordWrap(true);
3312 quickDesc->setOpenExternalLinks(true);
3313 quickLayout->addWidget(quickDesc);
3314
3315 quickTab->setWidget(quickContainer);
3316
3317 // TAB 3 - Control Point Editing
3318 QScrollArea *controlPointTab = new QScrollArea;
3319 controlPointTab->setWidgetResizable(true);
3320 controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3321 QWidget *controlPointContainer = new QWidget;
3322 QVBoxLayout *controlPointLayout = new QVBoxLayout;
3323 controlPointContainer->setLayout(controlPointLayout);
3324
3325 QLabel *controlPointTitle = new QLabel("<h2>Control Point Editing</h2>");
3326 controlPointLayout->addWidget(controlPointTitle);
3327
3328 QLabel *mouseLabel = new QLabel("<p><h3>When the \"Match\" tool "
3329 "is activated, the mouse buttons have the following function in the "
3330 "cube viewports of the main qview window:</h3>");
3331 mouseLabel->setWordWrap(true);
3332 mouseLabel->setScaledContents(true);
3333 controlPointLayout->addWidget(mouseLabel);
3334
3335 QLabel *controlPointDesc = new QLabel("<ul>"
3336 "<li>Left click - Edit the closest control point <b>Note:</b> "
3337 "All cubes in the control point must be displayed before loading the point</li>"
3338 "<li>Middle click - Delete the closest control point</li>"
3339 "<li>Right click - Create new control point at cursor location. This will bring up a new "
3340 "point dialog which allows you to enter a point id and will list all cube viewports, "
3341 "highlighting cubes where the point has been chosen by clicking on the cube's viewport. "
3342 "When the desired cubes have been chosen, select the \"Done\" button which will load the "
3343 "control point into the control point editor window which will allow the control measure "
3344 "positions to be refined.</li>");
3345 controlPointDesc->setWordWrap(true);
3346 controlPointLayout->addWidget(controlPointDesc);
3347
3348 QLabel *controlPointEditing = new QLabel(
3349 "<h4>Changing Control Measure Locations</h4>"
3350 "<p>Both the left and right control measure positions can be adjusted by:"
3351 "<ul>"
3352 "<li>Move the cursor location under the crosshair by clicking the left mouse "
3353 "button</li>"
3354 "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
3355 "<li>Move 1 pixel at a time by using arrow buttons above the right and left views</li>"
3356 "</ul></p>"
3357 "<h4>Other Point Editor Functions</h4>"
3358 "<p>Along the right border of the window:</p>"
3359 "<ul>"
3360 "<li><strong>Link Zoom</strong> This will link the two small viewports together when "
3361 "zooming (ie. If this is checked, if the left view is zoomed, the right view will "
3362 "match the left view's zoom factor. "
3363 "<b>Note:</b> Zooming is controlled from the left view.</li>"
3364 "<li><strong>No Rotate:</strong> Turn off the rotation and bring right view back to "
3365 "its original orientation</li>"
3366 "<li><strong>Rotate:</strong> Rotate the right view using either the dial "
3367 "or entering degrees </li>"
3368 "<li><strong>Show control points:</strong> Draw crosshairs at all control "
3369 "point locations visible within the view</li>"
3370 "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire "
3371 "view</li>"
3372 "<li><strong>Circle:</strong> Draw circle which may help center measure "
3373 "on a crater</li></ul"
3374 "<p>Below the left view:</p>"
3375 "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the "
3376 "left view window using the \"Blink Start\" button <img src=\"" + toolIconDir +
3377 "/blinkStart.png\" width=22 height=22> and \"Blink Stop\" button <img src=\"" +
3378 toolIconDir + "/blinkStop.png\" width=22 height=22>. The arrow keys above the left "
3379 "and right views and the keyboard arrow keys may be used to move the both views while "
3380 "blinking.</li>"
3381 "<li><strong>Register:</strong> Sub-pixel register the right view to "
3382 "the left view. A default registration template is used for setting parameters "
3383 "passed to the sub-pixel registration tool. The user may load in a predefined "
3384 "template or edit the current loaded template to influence successful "
3385 "co-registration results. For more information regarding the pattern matching "
3386 "functionlity or how to create a parameter template, refer to the Isis PatternMatch "
3387 "document and the <i>autoregtemplate</i> application.</li>"
3388 "<li><strong>Save Measures:</strong> Save the two control measures using the sample, "
3389 "line positions under the crosshairs.</li>"
3390 "<li><strong>Save Point:</strong> Save the control point to the control network.</li>"
3391 "</ul>");
3392 controlPointEditing->setWordWrap(true);
3393 controlPointLayout->addWidget(controlPointEditing);
3394
3395 controlPointTab->setWidget(controlPointContainer);
3396
3397 tabArea->addTab(overviewTab, "&Overview");
3398 tabArea->addTab(quickTab, "&Quick Start");
3399 tabArea->addTab(controlPointTab, "&Control Point Editing");
3400
3401 QHBoxLayout *buttonsLayout = new QHBoxLayout;
3402 // Flush the buttons to the right
3403 buttonsLayout->addStretch();
3404
3405 QPushButton *closeButton = new QPushButton("&Close");
3406 closeButton->setIcon(QIcon(FileName("$base/icons/guiStop.png").expanded()));
3407 closeButton->setDefault(true);
3408 connect(closeButton, SIGNAL(clicked()),
3409 helpDialog, SLOT(close()));
3410 buttonsLayout->addWidget(closeButton);
3411
3412 mainLayout->addLayout(buttonsLayout);
3413
3414 helpDialog->show();
3415 }
3416#endif
3417}
This is free and unencumbered software released into the public domain.
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
static QString UserName()
Returns the user name.
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition Buffer.h:138
virtual double Line() const
Returns the current line number.
Definition Camera.cpp:2740
virtual double Sample() const
Returns the current sample number.
Definition Camera.cpp:2720
virtual 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:156
virtual bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition Camera.cpp:382
This represents an ISIS control net in a project-based GUI interface.
Definition Control.h:65
ControlNet * controlNet()
Open and return a pointer to the ControlNet for this Control.
Definition Control.cpp:130
QString fileName() const
Access the name of the control network file associated with this Control.
Definition Control.cpp:252
a control measurement
bool IsEditLocked() const
Return value for p_editLock or implicit lock on reference measure.
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
Status SetCoordinate(double sample, double line)
Set the coordinate of the measurement.
QString GetChooserName() const
Return the chooser name.
QString GetCubeSerialNumber() const
Return the serial number of the cube containing the coordinate.
@ Manual
Hand Measured (e.g., qnet)
@ Candidate
(e.g., autoseed, interest) AKA predicted, unmeasured, unverified
@ RegisteredSubPixel
Registered to sub-pixel (e.g., pointreg)
@ RegisteredPixel
Registered to whole pixel (e.g.,pointreg)
Status SetType(MeasureType type)
Set how the coordinate was obtained.
Status SetCamera(Isis::Camera *camera)
Set pointer to camera associated with a measure.
Status SetChooserName()
Set chooser name to a user who last changed the coordinate.
a control network
Definition ControlNet.h:258
QPointer< QComboBox > m_templateComboBox
ComboBox of imported registration templates.
void setLockLeftMeasure(bool ignore)
Set the "EditLock" keyword of the measure shown in the left viewport to the value of the input parame...
void saveTemplateFileAs()
Save the contents of template editor to a file chosen by the user.
bool m_addMeasuresButton
Indicates whether or not to add "Add Measures(s) to Point".
void deletePoint(ControlPoint *controlPoint)
Gives user options for deleting a control point from the control network.
void setLockRightMeasure(bool ignore)
Set the "EditLock" keyword of the measure shown in the right viewport to the value of the input param...
QPointer< Control > m_control
Current Control.
QPointer< QLabel > m_rightMeasureType
Label for the right measure's adjustment type.
QPointer< QCheckBox > m_ignorePoint
Checkbox to ignore the current point.
void setIgnoreRightMeasure(bool ignore)
Set the "Ignore" keyword of the measure shown in the right viewport to the value of the input paramet...
void previousRightMeasure()
Selects the previous right measure when activated by key shortcut.
QPointer< ControlPoint > m_editPoint
The control point being edited.
void checkReference()
Change which measure is the reference.
void updateRightMeasureInfo()
Update the right measure information.
void colorizeSaveNetButton(bool reset=false)
Turn "Save Net" button text to red.
QPointer< QPushButton > m_reloadPoint
Button to reload current point to saved measures.
QPointer< QComboBox > m_rightCombo
Combobox to load right measure into right chip viewport.
bool m_changeAllGroundLocation
Change the ground source location of all fixed, constrained points in the network.
bool IsMeasureLocked(QString serialNumber)
Check for implicitly locked measure in m_editPoint.
void setEditPoint(ControlPoint *controlPoint, QString serialNumber="")
Slot called by Directory to set the control point for editing.
QPointer< QWidget > m_parent
Parent widget.
QPointer< QCheckBox > m_lockLeftMeasure
Checkbox to edit lock/unlock the left measure.
QPointer< QPushButton > m_saveNet
Button to save the current control network.
bool okToContinue()
Checks the state of the template registration file and determines if it is safe to continue opening a...
void resetTemplateComboBox(QString fileName)
Reset the selected template in the template combobox if the template selected by the user does not sa...
bool validateMeasureChange(ControlMeasure *m)
Validates a change to a control measure.
void setShapesForPoint(double latitude=Null, double longitude=Null)
Fill m_projectShapeNames with ALL shapes currently in project.
QPointer< ControlMeasureEditWidget > m_measureEditor
Pointer to control measure editor widget.
bool m_templateModified
Indicates if the registration template was edited.
QPointer< QAction > m_saveTemplateFile
Action to save a registration template file to disk.
QPointer< QComboBox > m_pointTypeCombo
Combobox to change the type of the current point.
QPointer< ControlMeasure > m_leftMeasure
Left control measure.
QString m_cnetFileName
Filename of the control network that is being modified.
bool setGroundSourceInfo()
Find the ground source location: First look at current edit point for parameter, AprioriXYZSourceFile...
void changeGroundLocationsInNet()
Change the location of all ground source locations in the ControlNet.
QPointer< QLabel > m_cnetFileNameLabel
Label with name of the control network file.
void setControl(Control *control)
New control network being edited.
QPointer< QComboBox > m_leftCombo
Combobox to load left measure into left chip viewport.
void initDem(QString demFile)
Initialize the given Dem and appropriate member variables for later use editing Fixed or Constrained ...
void saveChips()
Slot which calls ControlPointEditWidget slot to save chips.
QPointer< QCheckBox > m_ignoreLeftMeasure
Checkbox to ignore the left measure.
QString m_groundSN
Serial number of ground source file.
ControlMeasure * createTemporaryGroundMeasure()
Create a temporary measure to hold the ground point info for ground source.
void setSerialNumberList(SerialNumberList *snList)
Set the serial number list.
SerialNumberList * m_serialNumberList
Serial number list for the loaded cubes.
QPointer< QComboBox > m_radiusSourceCombo
ComboBox for selecting ground source.
void loadGroundMeasure()
Load ground measure into right side and add to file combo boxes.
void createControlPoint(double latitude, double longitude, Cube *cube=0, bool isGroundSource=false)
Create a new control point at the given latitude, longitude.
QPointer< QTextEdit > m_templateEditor
Text editor for editing the registration template.
void saveTemplateFile()
Save the file opened in the template editor.
QPointer< QCheckBox > m_lockRightMeasure
Checkbox to edit lock/unlock the right measure.
void createActions()
Creates the actions for the widget.
void addTemplates(TemplateList *templateList)
Add registration TemplateList to combobox when imported to project.
void viewTemplateFile()
Allows the user to view the template file that is currently set.
QStringList m_pointFiles
Associated files for current control point.
void measureSaved()
This method is connected with the measureSaved() signal from ControlMeasureEditWidget.
void openReferenceRadius()
Open a radius source using the shape model of the reference measure of m_editPoint.
FileName checkGroundFileLocation(FileName groundFile)
Ground source file from control net cannot be found, give user option to give new location.
bool m_cnetModified
Indicates if the control network has been modified.
void savePoint()
Save edit point to the Control Network.
void clearGroundSource()
Clear out the ground source used for Constrained or Fixed control points.
void setControlFromActive()
New active control was set from ipce.
void setPointType(int pointType)
Set the point type.
int m_numberProjectShapesWithPoint
Number of shapes containing control point.
void setTemplateFile(QString)
Appends the filename to the registrations path (unless this is the default template) and calls setTem...
QPointer< QAction > m_saveTemplateFileAs
Action to save a new registration template.
bool m_changeGroundLocationInNet
Change the ground source location.
QPointer< QAction > m_openTemplateFile
Action to open a registration template file to disk.
void setIgnorePoint(bool ignore)
Set point's "Ignore" keyword to the value of the input parameter.
void clearEditPoint()
Cleans up the edit point memory.
void reloadPoint()
Set both chip viewports to their original measures for the control point.
void loadPoint(QString serialNumber="")
Load point into ControlPointEditWidget.
void colorizeSavePointButton()
Refresh all necessary widgets in ControlPointEditWidget including the PointEditor and CubeViewports.
void updateSurfacePointInfo()
Update the Surface Point Information in the ControlPointEditWidget.
void openTemplateFile()
Prompt user for a registration template file to open.
QMap< QString, Shape * > m_nameToShapeMap
Map between Shape display name and object.
void nextRightMeasure()
Selects the next right measure when activated by key shortcut.
void createTemplateEditorWidget()
Creates the Widget which contains the template editor and its toolbar.
void setLockPoint(bool ignore)
Set point's "EditLock" keyword to the value of the input parameter.
QPalette m_saveDefaultPalette
Default color pallet of the "Save Point" button.
void selectLeftMeasure(int index)
Select left measure.
QStringList m_projectShapeNames
List of Shapes imported into project, at time of loaded CP.
QString m_lastUsedPointId
Point id of the last used control point.
QPointer< ControlNet > m_controlNet
Current control net.
void groundSourceFileSelectionChanged(int index)
Slot called when user changes selection in m_groundSourceCombo.
void writeTemplateFile(QString)
Write the contents of the template editor to the file provided.
void selectRightMeasure(int index)
Select right measure.
QPointer< QComboBox > m_groundSourceCombo
ComboBox for selecting ground source.
QGroupBox * createLeftMeasureGroupBox()
Creates the "Left Measure" groupbox.
void setTemplateModified()
Called when the template file is modified by the template editor.
QPointer< QWidget > m_templateEditorWidget
Template editor widget.
void showHideTemplateEditor()
Toggles the visibility of the template editor widget.
void setIgnoreLeftMeasure(bool ignore)
Set the "Ignore" keyword of the measure shown in the left viewport to the value of the input paramete...
QScopedPointer< Cube > m_rightCube
Right cube.
void saveNet()
This slot is needed because we cannot directly emit a signal with a ControlNet argument after the "Sa...
QPointer< QCheckBox > m_ignoreRightMeasure
Checkbox to ignore the right measure.
QPointer< QLabel > m_rightReference
Label indicating if right measure is the reference.
bool eventFilter(QObject *o, QEvent *e)
Event filter for ControlPointEditWidget.
QString m_groundFilename
File name of ground source.
QScopedPointer< Cube > m_leftCube
Left cube.
QPointer< QAction > m_closePointEditor
Action to close the point editor.
ControlPoint::SurfacePointSource::Source m_groundSourceType
SurfacePoint type of ground source.
void updateLeftMeasureInfo()
Update the left measure information.
QPointer< ControlMeasure > m_rightMeasure
Right control measure.
QGroupBox * createControlPointGroupBox()
Creates the "Control Point" groupbox.
void loadTemplateFile(QString)
Updates the current template file being used.
QSplitter * createTopSplitter()
Creates everything above the ControlPointEdit.
QPointer< QAction > m_saveChips
Action to save the registration chips Action to toggle visibility of the registration template editor...
QGroupBox * createRightMeasureGroupBox()
Create the "Right Measure" groupbox.
QString m_newGroundDir
Contains the ground source location.
QPointer< QLabel > m_ptIdValue
Label for the point id of the current point.
QPointer< QPushButton > m_savePoint
Button to save current point being edited.
QPointer< QLabel > m_leftReference
Label indicating if left measure is the reference.
bool m_demOpen
Has a radius source been opened?
ControlPointEditWidget(Directory *directory, QWidget *parent, bool addMeasures=false)
Consructs the ControlPointEditWidget widget.
double demRadius(double latitude, double longitude)
Return a radius values from the dem using bilinear interpolation.
void createPointEditor(QWidget *parent, bool addMeasures)
Create the widget for editing control points.
QPointer< QLabel > m_leftMeasureType
Label for the left measure's adjustment type.
QPointer< QCheckBox > m_lockPoint
Checkbox that locks/unlocks the current point.
A single control point.
Status
This is a return status for many of the mutating (setter) method calls.
@ PointLocked
This is returned when the operation requires Edit Lock to be false but it is currently true.
Status SetChooserName(QString name)
Set the point's chooser name.
int Delete(ControlMeasure *measure)
Remove a measurement from the control point, deleting reference measure is allowed.
void Add(ControlMeasure *measure)
Add a measurement to the control point, taking ownership of the measure in the process.
PointType GetType() const
PointType
These are the valid 'types' of point.
@ Free
A Free point is a Control Point that identifies common measurements between two or more cubes.
Status SetType(PointType newType)
Updates the control point's type.
Status SetAprioriSurfacePointSourceFile(QString sourceFile)
This updates the filename of where the apriori surface point came from.
Status SetAprioriSurfacePointSource(SurfacePointSource::Source source)
This updates the source of the surface point.
static QString PointTypeToString(PointType type)
Obtain a string representation of a given PointType.
QString GetId() const
Return the Id of the control point.
bool HasSerialNumber(QString serialNumber) const
Return true if given serial number exists in point.
bool HasAprioriSurfacePointSourceFile() const
Checks to see if the surface point source file has been set.
IO Handler for Isis Cubes.
Definition Cube.h:168
FileName externalCubeFileName() const
If this is an external cube label file, this will give you the cube dn file that this label reference...
Definition Cube.cpp:1568
Widget to display Isis cubes for qt apps.
Distance measurement, usually in meters.
Definition Distance.h:34
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
double meters() const
Get the distance in meters.
Definition Distance.cpp:85
File name manipulation and expansion.
Definition FileName.h:100
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition FileName.cpp:449
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition FileName.cpp:515
Isis exception class.
Definition IException.h:91
QString toString() const
Returns a string representation of this exception.
Pixel interpolator.
int Samples()
Returns the number of samples needed by the interpolator.
int Lines()
Returns the number of lines needed by the interpolator.
double HotSample()
Returns the sample coordinate of the center pixel in the buffer for the interpolator.
double HotLine()
Returns the line coordinate of the center pixel in the buffer for the interpolator.
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.
void setFiles(QStringList pointFiles)
Dialog used by ControlPointEditWidget to select a new location for ground source files.
bool changeControlNet()
Indicates whether the control network should be changed to reflect new ground source location.
bool changeAllGroundSourceLocation()
Indicates whether all subsequent ground source files should be found in new source directory.
Buffer for containing a two dimensional section of an image.
Definition Portal.h:36
void SetPosition(const double sample, const double line, const int band)
Sets the line and sample position of the buffer.
Definition Portal.h:93
QString fileName() const
Returns the filename used to initialise the Pvl object.
PvlEditDialog creates a QDialog window in which a QTextEdit box displays the contents of a pvl file.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition Sensor.cpp:212
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition Sensor.cpp:235
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
Serial Number list generator.
This represents a shape in a project-based GUI interface.
Definition Shape.h:66
QString fileName() const
Get the file name of the cube that this shape represents.
Definition Shape.cpp:360
Cube * cube()
Get the Cube * associated with this display property.
Definition Shape.cpp:308
Internalizes a list of shapes and allows for operations on the entire list.
Definition ShapeList.h:31
Obtain SPICE information for a spacecraft.
Definition Spice.h:283
void radii(Distance r[3]) const
Returns the radii of the body in km.
Definition Spice.cpp:937
Pixel value mapper.
Definition Stretch.h:58
This class defines a body-fixed surface point.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Distance GetLocalRadius() const
Return the radius of the surface point.
QString fileName() const
Get the file name that this Template represents.
Definition Template.cpp:49
QString importName() const
Get the name of the TemplateList this file was imported under.
Definition Template.cpp:67
QString type() const
Get the type of template in this TemplateList.
Universal Ground Map.
double Sample() const
Returns the current line value of the camera model or projection.
double Line() const
Returns the current line value of the camera model or projection.
bool SetUniversalGround(double lat, double lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.