9#include "ControlPointEditWidget.h"
31#include <QTableWidget>
35#include "Application.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"
46#include "IException.h"
49#include "MainWindow.h"
50#include "MdiCubeViewport.h"
51#include "NewControlPointDialog.h"
52#include "NewGroundSourceLocationDialog.h"
55#include "PvlEditDialog.h"
56#include "SerialNumber.h"
57#include "SerialNumberList.h"
60#include "SpecialPixel.h"
62#include "TemplateList.h"
64#include "UniversalGroundMap.h"
65#include "ViewportMainWindow.h"
79 bool addMeasures) :
QWidget(parent) {
81 m_directory = directory;
96 connect(
this, SIGNAL(newControlNetwork(
ControlNet *)),
99 connect(m_directory->project(), SIGNAL(templatesAdded(
TemplateList *)),
104 ControlPointEditWidget::~ControlPointEditWidget () {
109 QString ControlPointEditWidget::editPointId() {
121 ControlPoint *result = NULL;
156 setWindowTitle(
"Control Point Editor");
157 setObjectName(
"ControlPointEditWidget");
167 connect(
this, SIGNAL(newControlNetwork(
ControlNet *)),
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.");
186 connect(addMeasure, SIGNAL(clicked()),
this, SLOT(addMeasure()));
191 m_reloadPoint->setWhatsThis(
"Reload the measures for the control point"
192 " in the Chip Viewports to its saved values. ");
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.");
207 m_saveNet =
new QPushButton (
"Save Control Net");
209 m_saveNet->setToolTip(
"Save current control network. "
210 "<strong>Shortcut: S</strong>");
211 m_savePoint->setWhatsThis(
"Save the control network.");
218 QHBoxLayout * saveMeasureLayout =
new QHBoxLayout;
220 saveMeasureLayout->addWidget(addMeasure);
226 saveMeasureLayout->insertStretch(-1);
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.");
238 QList <TemplateList *> regTemplates = m_directory->project()->regTemplates();
240 foreach(
Template *templateFile, *templateList){
245 QFormLayout *templateFileLayout =
new QFormLayout();
254 QVBoxLayout * centralLayout =
new QVBoxLayout;
257 centralLayout->addLayout(templateFileLayout);
259 centralLayout->addStretch();
261 centralLayout->addLayout(saveMeasureLayout);
264 centralWidget->setLayout(centralLayout);
266 QScrollArea *scrollArea =
new QScrollArea();
267 scrollArea->setObjectName(
"ControlPointEditWidgetScroll");
268 scrollArea->setWidget(centralWidget);
269 scrollArea->setWidgetResizable(
true);
270 centralWidget->adjustSize();
272 QHBoxLayout *mainLayout =
new QHBoxLayout;
273 mainLayout->addWidget(scrollArea);
274 setLayout(mainLayout);
289 QHBoxLayout * measureLayout =
new QHBoxLayout;
293 QVBoxLayout * groupBoxesLayout =
new QVBoxLayout;
295 groupBoxesLayout->addStretch();
296 groupBoxesLayout->addLayout(measureLayout);
299 groupBoxesWidget->setLayout(groupBoxesLayout);
303 QSplitter * topSplitter =
new QSplitter;
304 topSplitter->addWidget(groupBoxesWidget);
325 m_numMeasures =
new QLabel;
327 m_aprioriLatitude =
new QLabel;
328 m_aprioriLongitude =
new QLabel;
329 m_aprioriRadius =
new QLabel;
337 connect(
this, SIGNAL(ignorePointChanged()),
m_ignorePoint, SLOT(toggle()));
340 for (
int i=0; i<ControlPoint::PointTypeCount; i++) {
344 QFormLayout *pointTypeLayout =
new QFormLayout;
353 QFormLayout *groundSourceLayout =
new QFormLayout;
355 QFormLayout *radiusSourceLayout =
new QFormLayout;
358 QVBoxLayout * mainLayout =
new QVBoxLayout;
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);
368 mainLayout->addLayout(pointTypeLayout);
371 QGroupBox * groupBox =
new QGroupBox(
"Control Point");
372 groupBox->setLayout(mainLayout);
387 m_leftCombo->setToolTip(
"Choose left control measure");
388 m_leftCombo->setWhatsThis(
"Choose left control measure identified by "
398 connect(
this, SIGNAL(ignoreLeftChanged()),
402 QVBoxLayout * leftLayout =
new QVBoxLayout;
409 QGroupBox * leftGroupBox =
new QGroupBox(
"Left Measure");
410 leftGroupBox->setLayout(leftLayout);
432 m_rightCombo->setToolTip(
"Choose right control measure. "
433 "<strong>Shortcuts: PageUp/PageDown</strong>");
434 m_rightCombo->setWhatsThis(
"Choose right control measure identified by "
436 "Note: PageUp selects previous measure; "
437 "PageDown selects next meausure.");
439 m_rightCombo->view()->setSelectionMode(QAbstractItemView::SingleSelection);
443 m_rightCombo->view()->setDragDropMode(QAbstractItemView::InternalMove);
447 QShortcut *nextMeasure =
new QShortcut(Qt::Key_PageDown,
this);
449 QShortcut *prevMeasure =
new QShortcut(Qt::Key_PageUp,
this);
460 connect(
this, SIGNAL(ignoreRightChanged()),
466 QVBoxLayout * rightLayout =
new QVBoxLayout;
473 QGroupBox * rightGroupBox =
new QGroupBox(
"Right Measure");
474 rightGroupBox->setLayout(rightLayout);
476 return rightGroupBox;
488 toolBar->addSeparator();
496 QVBoxLayout *mainLayout =
new QVBoxLayout;
497 mainLayout->addWidget(toolBar);
515 QString whatsThis =
"<b>Function:</b> Closes the Match Tool window for this point "
516 "<p><b>Shortcut:</b> Alt+F4 </p>";
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,
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.";
541 "&Open registration template",
this);
544 whatsThis =
"<b>Function:</b> Allows user to select a new file to set as "
545 "the registration template";
550 "&Save template file",
this);
558 "&Save template as...",
this);
583 if (latitude ==
Null || longitude ==
Null) {
597 cam->
SetImage(m.GetSample(),m.GetLine());
612 foreach (
ShapeList *shapeList, shapeLists) {
613 foreach (
Shape *shape, *shapeList) {
619 shapeNamesNoPoint<<shape->
fileName();
627 if (shapeNamesNoPoint.count() > 0) {
678 QString strippedCnetFilename = cnetDirs.value(cnetDirs.length() -1);
682 setWindowTitle(
"Control Point Editor- Control Network File: " +
m_cnetFileName);
696 if (m_directory->project()->activeControl()) {
697 m_control = m_directory->project()->activeControl();
702 setWindowTitle(
"Control Point Editor- Control Network File: " +
m_cnetFileName);
759 return groundMeasure;
776 cam->
SetImage(m.GetSample(),m.GetLine());
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);
793 groundMeasure->
SetCoordinate(m_groundGmap->Sample(), m_groundGmap->Line());
797 return groundMeasure;
813 ControlPoint::SurfacePointSource::Source groundSourceType =
814 ControlPoint::SurfacePointSource::None;
816 bool success =
false;
831 else if (
m_editPoint->HasAprioriSurfacePointSourceFile()) {
839 groundSourceType =
m_editPoint->GetAprioriSurfacePointSource();
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());
894 QFileInfo oldFile(groundFile.
expanded());
897 newGroundFile =
FileName(newFile.absoluteFilePath());
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) {
922 QFileInfo oldFile(groundFile.
expanded());
924 newGroundFile = newFile.absoluteFilePath();
930 newGroundFile = NULL;
936 newGroundFile = NULL;
940 return newGroundFile;
951 for (
int i = 0; i <
m_controlNet->GetNumPoints(); i++ ) {
954 FileName groundFile(cp->GetAprioriSurfacePointSourceFile());
955 QFileInfo oldFile(groundFile.
expanded());
957 groundFile = newFile.absoluteFilePath();
974 QString referenceSN =
m_editPoint->GetReferenceSN();
976 QScopedPointer<Cube> referenceCube(
new Cube(referenceFileName,
"r"));
977 PvlGroup kernels = referenceCube->group(
"Kernels");
978 QString shapeFile = kernels[
"ShapeModel"];
983 if (shapeFile.contains(
".cub")) {
984 if (shapeFile.contains(
"dem")) {
985 m_radiusSourceType = ControlPoint::RadiusSource::DEM;
988 m_radiusSourceType = ControlPoint::RadiusSource::Ellipsoid;
991 m_radiusFilename = shapeFile;
996 m_radiusSourceType = ControlPoint::RadiusSource::Ellipsoid;
999 refSpice->
radii(refRadii);
1000 m_demFile = QString::number(refRadii[0].meters()) +
", " +
1001 QString::number(refRadii[1].meters()) +
", " +
1002 QString::number(refRadii[2].meters());
1004 m_radiusFilename =
"";
1021 if (m_demFile == demFile) {
1025 m_demCube.reset(NULL);
1029 QApplication::setOverrideCursor(Qt::WaitCursor);
1031 QScopedPointer<Cube> newDemCube(
new Cube(demFile,
"r"));
1034 m_demCube.reset(newDemCube.take());
1037 QMessageBox::critical(
this,
"Error", e.
toString());
1038 QApplication::restoreOverrideCursor();
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);
1050 QApplication::restoreOverrideCursor();
1053 m_radiusSourceType = ControlPoint::RadiusSource::DEM;
1054 m_radiusFilename = demFile;
1056 QApplication::restoreOverrideCursor();
1084 m_demCube->pixelType(),
1087 m_demCube->read(*portal);
1154 m_groundGmap.reset(NULL);
1177 if (controlPoint->Parent() == NULL) {
1181 colorizeAllSaveButtons(
"red");
1188 colorizeAllSaveButtons(
"black");
1195 void ControlPointEditWidget::colorizeAllSaveButtons(QString color) {
1197 if (color ==
"black") {
1203 else if (color ==
"red") {
1236 QString ptId(
"Point ID: ");
1237 ptId += (QString) CPId;
1244 QString ptsize =
"Number of Measures: " +
1246 m_numMeasures->setText(ptsize);
1271 if (shape->radiusSource() == ControlPoint::RadiusSource::DEM) {
1281 if (
m_editPoint->HasAprioriSurfacePointSourceFile()) {
1287 if (!aprioriSurfacePointFile.
toString().isEmpty()) {
1291 QColor(Qt::darkGreen), Qt::ForegroundRole);
1293 QFont(
"DejaVu Sans", 10, QFont::Bold), Qt::FontRole);
1302 QColor(Qt::green), Qt::ForegroundRole);
1304 QFont(
"DejaVu Sans", 10, QFont::Bold), Qt::FontRole);
1322 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
1332 if (groundMeasure) {
1341 for (
int i=0; i<ControlPoint::PointTypeCount; i++) {
1359 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
1368 item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled);
1369 m_model->appendRow(item);
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);
1383 int rightIndex = -1;
1385 QString referenceSerialNumber;
1388 referenceSerialNumber =
m_editPoint->GetReferenceSN();
1392 if (!serialNumber.isEmpty() && serialNumber != referenceSerialNumber) {
1395 if (leftIndex == -1) {
1396 if (rightIndex == 0) {
1405 if (leftIndex == -1) {
1406 if (rightIndex == 0) {
1418 if (rightIndex <= 0) {
1419 if (leftIndex == 0) {
1428 if (rightIndex >
m_editPoint->GetNumMeasures()-1) rightIndex = 0;
1437 this->setVisible(
true);
1453 bool isGroundSource) {
1467 double samp = cam->
Sample();
1468 double line = cam->
Line();
1469 if (samp >= 1 && samp <= cam->Samples() &&
1470 line >= 1 && line <= cam->Lines()) {
1482 newPointDialog->
setFiles(pointFiles);
1490 if (shape->radiusSource() == ControlPoint::RadiusSource::DEM) {
1491 radiusSourceFiles<<shape->
fileName();
1494 newPointDialog->setRadiusSource(radiusSourceFiles);
1499 if (newPointDialog->exec() == QDialog::Accepted) {
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);
1519 QStringList selectedFiles = newPointDialog->selectedFiles();
1520 foreach (QString selectedFile, selectedFiles) {
1530 m->SetAprioriSample(cam->
Sample());
1531 m->SetAprioriLine(cam->
Line());
1542 if (isGroundPoint) {
1555 emit controlPointAdded(newPoint->
GetId());
1579 deletePointDialog->pointIdValue->setText(CPId);
1582 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
1585 deletePointDialog->fileList->addItem(file);
1588 if (deletePointDialog->exec()) {
1590 int numDeleted = deletePointDialog->fileList->selectedItems().count();
1593 if (deletePointDialog->deleteAllCheckBox->isChecked() ||
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,
1605 if (response == QMessageBox::No) {
1614 QMessageBox::information(
this,
"EditLocked Point",
1615 "This point is EditLocked and cannot be deleted.");
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;
1634 (
m_editPoint->GetRefMeasure()->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)) {
1648 if (numDeleted == 1) {
1655 if (
m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1660 if (lockedMeasures > 0) {
1661 QMessageBox::information(
this,
"EditLocked Measures",
1662 QString::number(lockedMeasures) +
" / "
1664 deletePointDialog->fileList->selectedItems().size()) +
1665 " measures are EditLocked and were not deleted.");
1675 emit cnetModified();
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)) {
1768 emit ignorePointChanged();
1771 emit ignoreLeftChanged();
1775 emit ignoreRightChanged();
1783 bool savedAMeasure =
false;
1789 savedAMeasure =
true;
1792 if (rightChangeOk) {
1795 savedAMeasure =
true;
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);
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);
1818 updateGroundPosition();
1830 if (savedAMeasure) {
1855 if (*m == *origMeasure)
return false;
1859 QString side =
"right";
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);
1878 if (response == QMessageBox::Yes) {
1879 m->SetEditLock(
false);
1880 if (side ==
"left") {
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)) {
1899 m->SetIgnored(
false);
1900 if (side ==
"left") {
1901 emit ignoreLeftChanged();
1904 emit ignoreRightChanged();
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)){
1931 origLeftMeasure->GetLine());
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,
1945 if (response == QMessageBox::Yes) {
1953 QVariant font =
m_leftCombo->itemData(iref,Qt::FontRole);
1954 m_leftCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1956 m_rightCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1971 if (side ==
"left") {
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,
2006 if (response == QMessageBox::Yes) {
2014 QVariant font =
m_leftCombo->itemData(iref,Qt::FontRole);
2015 m_leftCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2017 m_rightCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2042 void ControlPointEditWidget::updateGroundPosition() {
2053 m_groundGmap->SetImage(groundMeasure->GetSample(), groundMeasure->GetLine());
2055 double lat = m_groundGmap->UniversalLatitude();
2056 double lon = m_groundGmap->UniversalLongitude();
2061 m_radiusFilename.clear();
2064 m_demCube.reset(NULL);
2070 m_radiusFilename = shape->cube()->externalCubeFileName().toString();
2077 m_radiusSourceType =
m_editPoint->GetAprioriRadiusSource();
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);
2097 radius =
m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
2100 m_editPoint->SetAprioriRadiusSource(ControlPoint::RadiusSource::None);
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);
2110 m_editPoint->SetAprioriRadiusSource(m_radiusSourceType);
2111 m_editPoint->SetAprioriRadiusSourceFile(m_radiusFilename);
2117 radius =
m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
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);
2133 SurfacePoint aprioriPt =
m_editPoint->GetAprioriSurfacePoint();
2134 Distance latSigma = aprioriPt.GetLatSigmaDistance();
2135 Distance lonSigma = aprioriPt.GetLonSigmaDistance();
2136 Distance radiusSigma = aprioriPt.GetLocalRadiusSigma();
2140 aprioriPt.SetSphericalSigmasDistance(latSigma, lonSigma, radiusSigma);
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);
2161 QString fullGroundFilename;
2169 m_editPoint->SetAprioriSurfacePointSourceFile(fullGroundFilename);
2226 emit cnetModified();
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);
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);
2284 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
2341 QString message =
"Unable to change Ignored on point. Set EditLock ";
2342 message +=
" to False.";
2343 QMessageBox::critical(
this,
"Error", message);
2368 QMessageBox::warning(
this,
"Point Locked",
"Point is Edit Locked. You must un-lock point"
2369 " before changing a measure.");
2384 emit measureChanged();
2416 emit measureChanged();
2438 QMessageBox::warning(
this,
"Point Locked",
"Point is Edit Locked. You must un-lock point"
2439 " before changing a measure.");
2453 emit measureChanged();
2486 emit measureChanged();
2502 if (curIndex < m_rightCombo->count() - 1) {
2551 QString message =
"Make sure the correct cube is opened.\n\n";
2553 QMessageBox::critical(
this,
"Error", message);
2600 QString message =
"Make sure the correct cube is opened.\n\n";
2602 QMessageBox::critical(
this,
"Error", message);
2655 QString s =
"Reference: ";
2665 s =
"Measure Type: ";
2701 QString s =
"Reference: ";
2712 s =
"Measure Type: ";
2734 if(e->type() != QEvent::Leave)
return false;
2756 int r = QMessageBox::warning(
this, tr(
"OK to continue?"),
2757 tr(
"The currently opened registration template has been modified.\n"
2759 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2762 if (r == QMessageBox::Yes)
2764 else if (r == QMessageBox::Cancel)
2782 QString filename = QFileDialog::getOpenFileName(
this,
2783 "Select a registration template",
".",
2784 "Registration template files (*.def *.pvl);;All files (*)");
2786 if (filename.isEmpty())
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);
2809 QTextStream stream(&file);
2814 sb->setValue(sb->minimum());
2851 QString filename = QFileDialog::getSaveFileName(
this,
2852 "Save registration template",
".",
2853 "Registration template files (*.def *.pvl);;All files (*)");
2855 if (filename.isEmpty())
2880 QMessageBox::warning(
this,
"Error", message);
2884 QString expandedFileName(
FileName((QString) fn).expanded());
2886 QFile file(expandedFileName);
2888 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2889 QString msg =
"Failed to save template file to \"" + fn +
"\"\nDo you "
2891 QMessageBox::warning(
this,
"IO Error", msg);
2896 QTextStream stream(&file);
2927 registrationDialog.setWindowTitle(
"View or Edit Template File: "
2929 registrationDialog.resize(550,360);
2930 registrationDialog.exec();
2934 QMessageBox::information(
this,
"Error", message);
2969 if(templateList->
type() ==
"registrations") {
2970 for(
int i = 0; i < templateList->size(); i++) {
2972 +
"/" +
FileName(templateList->at(i)->fileName()).
name());
2986 QString expandedFileName = filename;
2987 if(!filename.startsWith(
"$base")){
2988 expandedFileName = m_directory->project()->templateRoot()
2989 +
"/registrations/" + filename;
3004 if(fileName.startsWith(
"$base")) {
3008 int size = components.size();
3009 int index =
m_templateComboBox->findText(components[size - 2] +
"/" + components[size - 1]);
3033 s =
"Apriori Latitude: Null";
3036 s =
"Apriori Latitude: " +
3039 m_aprioriLatitude->setText(s);
3041 s =
"Apriori Longitude: Null";
3044 s =
"Apriori Longitude: " +
3047 m_aprioriLongitude->setText(s);
3049 s =
"Apriori Radius: Null";
3052 s =
"Apriori Radius: " +
3056 m_aprioriRadius->setText(s);
3104 QColor qc = Qt::red;
3106 p.setColor(QPalette::ButtonText,qc);
3126 QColor qc = Qt::red;
3128 p.setColor(QPalette::ButtonText,qc);
3152 (
m_editPoint->GetReferenceSN() == serialNumber)) {
3157 return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
3191 void ControlPointEditWidget::showHelp() {
3194 helpDialog->setWindowTitle(
"Match Tool Help");
3196 QVBoxLayout *mainLayout =
new QVBoxLayout;
3197 helpDialog->setLayout(mainLayout);
3199 QLabel *matchTitle =
new QLabel(
"<h2>Match Tool</h2>");
3200 mainLayout->addWidget(matchTitle);
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);
3209 QTabWidget *tabArea =
new QTabWidget;
3210 tabArea->setDocumentMode(
true);
3211 mainLayout->addWidget(tabArea);
3214 QScrollArea *overviewTab =
new QScrollArea;
3215 overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3216 overviewTab->setWidgetResizable(
true);
3218 QVBoxLayout *overviewLayout =
new QVBoxLayout;
3219 overviewContainer->setLayout(overviewLayout);
3221 QLabel *purposeTitle =
new QLabel(
"<h2>Purpose</h2>");
3222 overviewLayout->addWidget(purposeTitle);
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);
3252 overviewTab->setWidget(overviewContainer);
3255 QScrollArea *quickTab =
new QScrollArea;
3256 quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3257 quickTab->setWidgetResizable(
true);
3259 QVBoxLayout *quickLayout =
new QVBoxLayout;
3260 quickContainer->setLayout(quickLayout);
3262 QLabel *quickTitle =
new QLabel(
"<h2>Quick Start</h2>");
3263 quickLayout->addWidget(quickTitle);
3265 QLabel *quickSubTitle =
new QLabel(
"<h3>Preparation:</h3>");
3266 quickLayout->addWidget(quickSubTitle);
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);
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);
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 "
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 "
3293 fileButtons->setWordWrap(
true);
3294 quickLayout->addWidget(fileButtons);
3296 QLabel *quickFunctionTitle =
new QLabel(
"<h3>Cube Viewport Functions:</h3>");
3297 quickLayout->addWidget(quickFunctionTitle);
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);
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);
3315 quickTab->setWidget(quickContainer);
3318 QScrollArea *controlPointTab =
new QScrollArea;
3319 controlPointTab->setWidgetResizable(
true);
3320 controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3322 QVBoxLayout *controlPointLayout =
new QVBoxLayout;
3323 controlPointContainer->setLayout(controlPointLayout);
3325 QLabel *controlPointTitle =
new QLabel(
"<h2>Control Point Editing</h2>");
3326 controlPointLayout->addWidget(controlPointTitle);
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);
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);
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:"
3352 "<li>Move the cursor location under the crosshair by clicking the left mouse "
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>"
3357 "<h4>Other Point Editor Functions</h4>"
3358 "<p>Along the right border of the window:</p>"
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 "
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 "
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>"
3392 controlPointEditing->setWordWrap(
true);
3393 controlPointLayout->addWidget(controlPointEditing);
3395 controlPointTab->setWidget(controlPointContainer);
3397 tabArea->addTab(overviewTab,
"&Overview");
3398 tabArea->addTab(quickTab,
"&Quick Start");
3399 tabArea->addTab(controlPointTab,
"&Control Point Editing");
3401 QHBoxLayout *buttonsLayout =
new QHBoxLayout;
3403 buttonsLayout->addStretch();
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);
3412 mainLayout->addLayout(buttonsLayout);
This is free and unencumbered software released into the public domain.
double degrees() const
Get the angle in units of Degrees.
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
static QString UserName()
Returns the user name.
double * DoubleBuffer() const
Returns the value of the shape buffer.
virtual double Line() const
Returns the current line number.
virtual double Sample() const
Returns the current sample number.
virtual bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
virtual bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
This represents an ISIS control net in a project-based GUI interface.
ControlNet * controlNet()
Open and return a pointer to the ControlNet for this Control.
QString fileName() const
Access the name of the control network file associated with this Control.
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.
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.
FileName externalCubeFileName() const
If this is an external cube label file, this will give you the cube dn file that this label reference...
Widget to display Isis cubes for qt apps.
Distance measurement, usually in meters.
@ Meters
The distance is being specified in meters.
double meters() const
Get the distance in meters.
File name manipulation and expansion.
bool fileExists() const
Returns true if the file exists; false otherwise.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
QString toString() const
Returns a string representation of this exception.
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.
void SetPosition(const double sample, const double line, const int band)
Sets the line and sample position of the buffer.
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.
Container for cube-like labels.
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
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.
QString fileName() const
Get the file name of the cube that this shape represents.
Cube * cube()
Get the Cube * associated with this display property.
Internalizes a list of shapes and allows for operations on the entire list.
Obtain SPICE information for a spacecraft.
void radii(Distance r[3]) const
Returns the radii of the body in km.
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.
QString importName() const
Get the name of the TemplateList this file was imported under.
QString type() const
Get the type of template in this TemplateList.
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.
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.