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 *)),
104 ControlPointEditWidget::~ControlPointEditWidget () {
109 QString ControlPointEditWidget::editPointId() {
119 ControlPoint *ControlPointEditWidget::editPoint() {
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 $ISISROOT/doc/documents/"
236 "PatternMatch/PatternMatch.html for a description of the "
237 "contents of this file.");
241 foreach(
Template *templateFile, *templateList){
246 QFormLayout *templateFileLayout =
new QFormLayout();
255 QVBoxLayout * centralLayout =
new QVBoxLayout;
258 centralLayout->addLayout(templateFileLayout);
260 centralLayout->addStretch();
262 centralLayout->addLayout(saveMeasureLayout);
265 centralWidget->setLayout(centralLayout);
267 QScrollArea *scrollArea =
new QScrollArea();
268 scrollArea->setObjectName(
"ControlPointEditWidgetScroll");
269 scrollArea->setWidget(centralWidget);
270 scrollArea->setWidgetResizable(
true);
271 centralWidget->adjustSize();
273 QHBoxLayout *mainLayout =
new QHBoxLayout;
274 mainLayout->addWidget(scrollArea);
275 setLayout(mainLayout);
290 QHBoxLayout * measureLayout =
new QHBoxLayout;
294 QVBoxLayout * groupBoxesLayout =
new QVBoxLayout;
296 groupBoxesLayout->addStretch();
297 groupBoxesLayout->addLayout(measureLayout);
300 groupBoxesWidget->setLayout(groupBoxesLayout);
304 QSplitter * topSplitter =
new QSplitter;
305 topSplitter->addWidget(groupBoxesWidget);
326 m_numMeasures =
new QLabel;
328 m_aprioriLatitude =
new QLabel;
329 m_aprioriLongitude =
new QLabel;
330 m_aprioriRadius =
new QLabel;
338 connect(
this, SIGNAL(ignorePointChanged()),
m_ignorePoint, SLOT(toggle()));
341 for (
int i=0; i<ControlPoint::PointTypeCount; i++) {
345 QFormLayout *pointTypeLayout =
new QFormLayout;
354 QFormLayout *groundSourceLayout =
new QFormLayout;
356 QFormLayout *radiusSourceLayout =
new QFormLayout;
359 QVBoxLayout * mainLayout =
new QVBoxLayout;
361 mainLayout->addWidget(m_numMeasures);
362 mainLayout->addLayout(groundSourceLayout);
363 mainLayout->addLayout(radiusSourceLayout);
364 mainLayout->addWidget(m_aprioriLatitude);
365 mainLayout->addWidget(m_aprioriLongitude);
366 mainLayout->addWidget(m_aprioriRadius);
369 mainLayout->addLayout(pointTypeLayout);
372 QGroupBox * groupBox =
new QGroupBox(
"Control Point");
373 groupBox->setLayout(mainLayout);
388 m_leftCombo->setToolTip(
"Choose left control measure");
389 m_leftCombo->setWhatsThis(
"Choose left control measure identified by "
399 connect(
this, SIGNAL(ignoreLeftChanged()),
403 QVBoxLayout * leftLayout =
new QVBoxLayout;
410 QGroupBox * leftGroupBox =
new QGroupBox(
"Left Measure");
411 leftGroupBox->setLayout(leftLayout);
433 m_rightCombo->setToolTip(
"Choose right control measure. "
434 "<strong>Shortcuts: PageUp/PageDown</strong>");
435 m_rightCombo->setWhatsThis(
"Choose right control measure identified by "
437 "Note: PageUp selects previous measure; "
438 "PageDown selects next meausure.");
440 m_rightCombo->view()->setSelectionMode(QAbstractItemView::SingleSelection);
444 m_rightCombo->view()->setDragDropMode(QAbstractItemView::InternalMove);
448 QShortcut *nextMeasure =
new QShortcut(Qt::Key_PageDown,
this);
450 QShortcut *prevMeasure =
new QShortcut(Qt::Key_PageUp,
this);
461 connect(
this, SIGNAL(ignoreRightChanged()),
467 QVBoxLayout * rightLayout =
new QVBoxLayout;
474 QGroupBox * rightGroupBox =
new QGroupBox(
"Right Measure");
475 rightGroupBox->setLayout(rightLayout);
477 return rightGroupBox;
489 toolBar->addSeparator();
497 QVBoxLayout *mainLayout =
new QVBoxLayout;
498 mainLayout->addWidget(toolBar);
516 QString whatsThis =
"<b>Function:</b> Closes the Match Tool window for this point "
517 "<p><b>Shortcut:</b> Alt+F4 </p>";
521 m_showHideTemplateEditor =
new QAction(QIcon(
FileName(
"base/icons/view_text.png").expanded()),
522 "&View/edit registration template",
this);
523 m_showHideTemplateEditor->setCheckable(
true);
524 m_showHideTemplateEditor->setToolTip(
"View and/or edit the registration template");
525 m_showHideTemplateEditor->setStatusTip(
"View and/or edit the registration template");
526 whatsThis =
"<b>Function:</b> Displays the curent registration template. "
527 "The user may edit and save changes under a chosen filename.";
528 m_showHideTemplateEditor->setWhatsThis(whatsThis);
529 connect(m_showHideTemplateEditor, SIGNAL(triggered()),
this,
533 "Save registration chips",
this);
534 m_saveChips->setToolTip(
"Save registration chips");
535 m_saveChips->setStatusTip(
"Save registration chips");
536 whatsThis =
"<b>Function:</b> Save registration chips to file. "
537 "Each chip: pattern, search, fit will be saved to a separate file.";
542 "&Open registration template",
this);
545 whatsThis =
"<b>Function:</b> Allows user to select a new file to set as "
546 "the registration template";
551 "&Save template file",
this);
559 "&Save template as...",
this);
584 if (latitude ==
Null || longitude ==
Null) {
590 latitude = sPt.GetLatitude().degrees();
591 longitude = sPt.GetLongitude().degrees();
598 cam->SetImage(m.GetSample(),m.GetLine());
599 latitude = cam->UniversalLatitude();
600 longitude = cam->UniversalLongitude();
612 QList<ShapeList *> shapeLists = m_directory->
project()->shapes();
613 foreach (
ShapeList *shapeList, shapeLists) {
614 foreach (
Shape *shape, *shapeList) {
616 if (gmap->SetUniversalGround(latitude, longitude)) {
620 shapeNamesNoPoint<<shape->
fileName();
628 if (shapeNamesNoPoint.count() > 0) {
679 QString strippedCnetFilename = cnetDirs.value(cnetDirs.length() -1);
683 setWindowTitle(
"Control Point Editor- Control Network File: " +
m_cnetFileName);
703 setWindowTitle(
"Control Point Editor- Control Network File: " +
m_cnetFileName);
760 return groundMeasure;
769 lat = sPt.GetLatitude().degrees();
770 lon = sPt.GetLongitude().degrees();
777 cam->SetImage(m.GetSample(),m.GetLine());
778 lat = cam->UniversalLatitude();
779 lon = cam->UniversalLongitude();
783 if (!m_groundGmap->SetUniversalGround(lat,lon)) {
784 QString message =
"This point does not exist on the ground source.\n";
785 message +=
"Latitude = " + QString::number(lat);
786 message +=
" Longitude = " + QString::number(lon);
787 message +=
"\n A ground measure will not be created.";
788 QMessageBox::warning(
this,
"Warning", message);
794 groundMeasure->SetCoordinate(m_groundGmap->Sample(), m_groundGmap->Line());
795 groundMeasure->SetChooserName(
"GroundMeasureTemporary");
798 return groundMeasure;
814 ControlPoint::SurfacePointSource::Source groundSourceType =
815 ControlPoint::SurfacePointSource::None;
817 bool success =
false;
832 else if (
m_editPoint->HasAprioriSurfacePointSourceFile()) {
836 if (!groundFile.fileExists()) {
840 groundSourceType =
m_editPoint->GetAprioriSurfacePointSource();
854 QScopedPointer<Cube> groundCube(
new Cube(groundFile,
"r"));
855 m_groundGmap.reset(NULL);
856 QScopedPointer<UniversalGroundMap> newGroundGmap(
new UniversalGroundMap(*groundCube));
857 m_groundGmap.reset(newGroundGmap.take());
889 if (!groundFile.fileExists()) {
895 QFileInfo oldFile(groundFile.expanded());
898 newGroundFile =
FileName(newFile.absoluteFilePath());
906 QString message =
"Ground Source file " + groundFile.expanded();
907 message +=
" doesn't exist. Has the file moved? Would you like to enter a new location for"
908 " this ground source?";
909 int ret = QMessageBox::question(
this,
"Ground Source not found", message);
910 if (ret == QMessageBox::Yes) {
913 "New Ground Source Location", dir);
914 if (dialog->exec() == QDialog::Accepted) {
923 QFileInfo oldFile(groundFile.expanded());
925 newGroundFile = newFile.absoluteFilePath();
931 newGroundFile = NULL;
937 newGroundFile = NULL;
941 return newGroundFile;
952 for (
int i = 0; i <
m_controlNet->GetNumPoints(); i++ ) {
954 if (cp->HasAprioriSurfacePointSourceFile()) {
955 FileName groundFile(cp->GetAprioriSurfacePointSourceFile());
956 QFileInfo oldFile(groundFile.expanded());
958 groundFile = newFile.absoluteFilePath();
959 cp->SetAprioriSurfacePointSourceFile(groundFile.expanded());
975 QString referenceSN =
m_editPoint->GetReferenceSN();
977 QScopedPointer<Cube> referenceCube(
new Cube(referenceFileName,
"r"));
978 PvlGroup kernels = referenceCube->group(
"Kernels");
979 QString shapeFile = kernels[
"ShapeModel"];
984 if (shapeFile.contains(
".cub")) {
985 if (shapeFile.contains(
"dem")) {
986 m_radiusSourceType = ControlPoint::RadiusSource::DEM;
989 m_radiusSourceType = ControlPoint::RadiusSource::Ellipsoid;
992 m_radiusFilename = shapeFile;
997 m_radiusSourceType = ControlPoint::RadiusSource::Ellipsoid;
1000 refSpice->radii(refRadii);
1001 m_demFile = QString::number(refRadii[0].meters()) +
", " +
1002 QString::number(refRadii[1].meters()) +
", " +
1003 QString::number(refRadii[2].meters());
1005 m_radiusFilename =
"";
1022 if (m_demFile == demFile) {
1026 m_demCube.reset(NULL);
1030 QApplication::setOverrideCursor(Qt::WaitCursor);
1032 QScopedPointer<Cube> newDemCube(
new Cube(demFile,
"r"));
1035 m_demCube.reset(newDemCube.take());
1038 QMessageBox::critical(
this,
"Error", e.toString());
1039 QApplication::restoreOverrideCursor();
1045 if (!m_demCube->hasTable(
"ShapeModelStatistics")) {
1046 QString message = m_demFile +
" is not a DEM.";
1047 QMessageBox::critical(
this,
"Error", message);
1048 m_demCube.reset(NULL);
1051 QApplication::restoreOverrideCursor();
1054 m_radiusSourceType = ControlPoint::RadiusSource::DEM;
1055 m_radiusFilename = demFile;
1057 QApplication::restoreOverrideCursor();
1073 if (!demMap->SetUniversalGround(latitude, longitude)) {
1084 Portal *portal =
new Portal(interp->Samples(), interp->Lines(),
1085 m_demCube->pixelType(),
1086 interp->HotSample(), interp->HotLine());
1087 portal->SetPosition(demMap->Sample(), demMap->Line(), 1);
1088 m_demCube->read(*portal);
1089 double radius = interp->Interpolate(demMap->Sample(), demMap->Line(),
1090 portal->DoubleBuffer());
1155 m_groundGmap.reset(NULL);
1178 if (controlPoint->Parent() == NULL) {
1182 colorizeAllSaveButtons(
"red");
1189 colorizeAllSaveButtons(
"black");
1196 void ControlPointEditWidget::colorizeAllSaveButtons(QString color) {
1198 if (color ==
"black") {
1204 else if (color ==
"red") {
1237 QString ptId(
"Point ID: ");
1238 ptId += (QString) CPId;
1245 QString ptsize =
"Number of Measures: " +
1247 m_numMeasures->setText(ptsize);
1272 if (shape->radiusSource() == ControlPoint::RadiusSource::DEM) {
1282 if (
m_editPoint->HasAprioriSurfacePointSourceFile()) {
1285 if (!aprioriSurfacePointFile.fileExists()) {
1288 if (!aprioriSurfacePointFile.toString().isEmpty()) {
1292 QColor(Qt::darkGreen), Qt::ForegroundRole);
1294 QFont(
"DejaVu Sans", 10, QFont::Bold), Qt::FontRole);
1303 QColor(Qt::green), Qt::ForegroundRole);
1305 QFont(
"DejaVu Sans", 10, QFont::Bold), Qt::FontRole);
1323 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
1325 if (m.GetChooserName() ==
"GroundMeasureTemporary") {
1333 if (groundMeasure) {
1342 for (
int i=0; i<ControlPoint::PointTypeCount; i++) {
1360 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
1369 item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled);
1370 m_model->appendRow(item);
1375 (QString)m.GetCubeSerialNumber() ==
m_editPoint->GetReferenceSN()) {
1376 m_leftCombo->setItemData(i,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1377 m_rightCombo->setItemData(i,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1384 int rightIndex = -1;
1386 QString referenceSerialNumber;
1389 referenceSerialNumber =
m_editPoint->GetReferenceSN();
1393 if (!serialNumber.isEmpty() && serialNumber != referenceSerialNumber) {
1396 if (leftIndex == -1) {
1397 if (rightIndex == 0) {
1406 if (leftIndex == -1) {
1407 if (rightIndex == 0) {
1419 if (rightIndex <= 0) {
1420 if (leftIndex == 0) {
1429 if (rightIndex >
m_editPoint->GetNumMeasures()-1) rightIndex = 0;
1438 this->setVisible(
true);
1454 bool isGroundSource) {
1466 if (cam->SetUniversalGround(latitude, longitude)) {
1468 double samp = cam->Sample();
1469 double line = cam->Line();
1470 if (samp >= 1 && samp <= cam->Samples() &&
1471 line >= 1 && line <= cam->Lines()) {
1483 newPointDialog->setFiles(pointFiles);
1491 if (shape->radiusSource() == ControlPoint::RadiusSource::DEM) {
1492 radiusSourceFiles<<shape->
fileName();
1495 newPointDialog->setRadiusSource(radiusSourceFiles);
1500 if (newPointDialog->exec() == QDialog::Accepted) {
1508 QString message =
"A ControlPoint with Point Id = [" + newPoint->
GetId();
1509 message +=
"] already exists. Re-enter Point Id for this ControlPoint.";
1510 QMessageBox::warning(
this,
"New Point Id", message);
1520 QStringList selectedFiles = newPointDialog->selectedFiles();
1521 foreach (QString selectedFile, selectedFiles) {
1526 m->SetCubeSerialNumber(sn);
1529 cam->SetUniversalGround(latitude, longitude);
1530 m->SetCoordinate(cam->Sample(),cam->Line());
1531 m->SetAprioriSample(cam->Sample());
1532 m->SetAprioriLine(cam->Line());
1543 if (isGroundPoint) {
1556 emit controlPointAdded(newPoint->
GetId());
1580 deletePointDialog->pointIdValue->setText(CPId);
1583 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
1586 deletePointDialog->fileList->addItem(file);
1589 if (deletePointDialog->exec()) {
1591 int numDeleted = deletePointDialog->fileList->selectedItems().count();
1594 if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1598 if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1599 QString message =
"You have selected all measures in this point to be deleted. This "
1600 "control point will be deleted. Do you want to delete this control point?";
1601 int response = QMessageBox::question(
this,
1602 "Delete control point", message,
1603 QMessageBox::Yes | QMessageBox::No,
1606 if (response == QMessageBox::No) {
1615 QMessageBox::information(
this,
"EditLocked Point",
1616 "This point is EditLocked and cannot be deleted.");
1628 int lockedMeasures = 0;
1629 for (
int i=0; i<deletePointDialog->fileList->count(); i++) {
1630 QListWidgetItem *item = deletePointDialog->fileList->item(i);
1631 if (!item->isSelected())
continue;
1635 (
m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
1637 QString message =
"You are trying to delete the Reference measure."
1638 " Do you really want to delete the Reference measure?";
1639 switch (QMessageBox::question(
this,
1640 "Delete Reference measure?", message,
1641 "&Yes",
"&No", 0, 0)) {
1649 if (numDeleted == 1) {
1656 if (
m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1661 if (lockedMeasures > 0) {
1662 QMessageBox::information(
this,
"EditLocked Measures",
1663 QString::number(lockedMeasures) +
" / "
1665 deletePointDialog->fileList->selectedItems().size()) +
1666 " measures are EditLocked and were not deleted.");
1676 emit cnetModified();
1762 QString message =
"You are saving changes to a measure on an ignored ";
1763 message +=
"point. Do you want to set Ignore = False on the point and ";
1764 message +=
"both measures?";
1765 switch (QMessageBox::question(
this,
"Save Measure", message,
"&Yes",
"&No", 0, 0)) {
1769 emit ignorePointChanged();
1772 emit ignoreLeftChanged();
1776 emit ignoreRightChanged();
1784 bool savedAMeasure =
false;
1790 savedAMeasure =
true;
1793 if (rightChangeOk) {
1796 savedAMeasure =
true;
1807 QString message =
"This control point is edit locked. The Apriori latitude, longitude and ";
1808 message +=
"radius cannot be updated. You must first unlock the point by clicking the ";
1809 message +=
"check box above labeled \"Edit Lock Point\".";
1810 QMessageBox::warning(
this,
"Point Locked", message);
1814 QString message =
"This is a Constrained or Fixed point and the reference measure is ";
1815 message +=
"Ignored. Unset the Ignore flag on the reference measure before saving.";
1816 QMessageBox::warning(
this,
"Point Locked", message);
1819 updateGroundPosition();
1831 if (savedAMeasure) {
1853 m_editPoint->GetMeasure(m->GetCubeSerialNumber());
1856 if (*m == *origMeasure)
return false;
1860 QString side =
"right";
1861 if (m->GetCubeSerialNumber() ==
m_leftMeasure->GetCubeSerialNumber()) {
1872 if (origMeasure->IsEditLocked() && m->IsEditLocked()) {
1873 QString message =
"The " + side +
" measure is editLocked ";
1874 message +=
"for editing. Do you want to set EditLock = False for this ";
1875 message +=
"measure?";
1876 int response = QMessageBox::question(
this,
"Save Measure",
1877 message, QMessageBox::Yes | QMessageBox::No);
1879 if (response == QMessageBox::Yes) {
1880 m->SetEditLock(
false);
1881 if (side ==
"left") {
1894 if (origMeasure->IsIgnored() && m->IsIgnored()) {
1895 QString message =
"The " + side +
"measure is ignored. ";
1896 message +=
"Do you want to set Ignore = False on the measure?";
1897 switch (QMessageBox::question(
this,
"Save Measure", message,
"&Yes",
"&No", 0, 0)) {
1900 m->SetIgnored(
false);
1901 if (side ==
"left") {
1902 emit ignoreLeftChanged();
1905 emit ignoreRightChanged();
1916 if (refMeasure->GetCubeSerialNumber() == m->GetCubeSerialNumber()) {
1917 if (m->GetSample() != origMeasure->GetSample() || m->GetLine() != origMeasure->GetLine()) {
1918 QString message =
"You are making a change to the reference measure. You ";
1919 message +=
"may need to move all of the other measures to match the new ";
1920 message +=
" coordinate of the reference measure. Do you really want to ";
1921 message +=
" change the reference measure's location? ";
1922 switch(QMessageBox::question(
this,
"Save Measure",
1923 message,
"&Yes",
"&No", 0, 0)){
1932 origLeftMeasure->GetLine());
1938 else if (side ==
"left" && (refMeasure->GetCubeSerialNumber() != m->GetCubeSerialNumber())) {
1939 QString message =
"This point already contains a reference measure. ";
1940 message +=
"Would you like to replace it with the measure on the left?";
1941 int response = QMessageBox::question(
this,
1942 "Save Measure", message,
1943 QMessageBox::Yes | QMessageBox::No,
1946 if (response == QMessageBox::Yes) {
1954 QVariant font =
m_leftCombo->itemData(iref,Qt::FontRole);
1955 m_leftCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1957 m_rightCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1966 m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
1972 if (side ==
"left") {
1973 m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
1999 if (refMeasure->GetCubeSerialNumber() !=
m_leftMeasure->GetCubeSerialNumber()) {
2000 QString message =
"This point already contains a reference measure. ";
2001 message +=
"Would you like to replace it with the measure on the left?";
2002 int response = QMessageBox::question(
this,
2003 "Match Tool Save Measure", message,
2004 QMessageBox::Yes | QMessageBox::No,
2007 if (response == QMessageBox::Yes) {
2015 QVariant font =
m_leftCombo->itemData(iref,Qt::FontRole);
2016 m_leftCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2018 m_rightCombo->setItemData(iref,QFont(
"DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
2043 void ControlPointEditWidget::updateGroundPosition() {
2054 m_groundGmap->SetImage(groundMeasure->GetSample(), groundMeasure->GetLine());
2056 double lat = m_groundGmap->UniversalLatitude();
2057 double lon = m_groundGmap->UniversalLongitude();
2062 m_radiusFilename.clear();
2065 m_demCube.reset(NULL);
2071 m_radiusFilename = shape->cube()->externalCubeFileName().toString();
2078 m_radiusSourceType =
m_editPoint->GetAprioriRadiusSource();
2092 if (radius ==
Null) {
2093 QString msg =
"Could not read radius from DEM, will default to "
2094 "local radius of reference measure.";
2095 QMessageBox::warning(
this,
"Warning", msg);
2098 radius =
m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
2101 m_editPoint->SetAprioriRadiusSource(ControlPoint::RadiusSource::None);
2104 QString message =
"Error trying to get radius at this pt. "
2105 "Lat/Lon does not fall on the reference measure. "
2106 "Cannot save this measure.";
2107 QMessageBox::critical(
this,
"Error",message);
2111 m_editPoint->SetAprioriRadiusSource(m_radiusSourceType);
2112 m_editPoint->SetAprioriRadiusSourceFile(m_radiusFilename);
2118 radius =
m_editPoint->GetRefMeasure()->Camera()->LocalRadius().meters();
2121 QString message =
"Error trying to get radius at this pt. "
2122 "Lat/Lon does not fall on the reference measure. "
2123 "Cannot save this measure.";
2124 QMessageBox::critical(
this,
"Error",message);
2134 SurfacePoint aprioriPt =
m_editPoint->GetAprioriSurfacePoint();
2135 Distance latSigma = aprioriPt.GetLatSigmaDistance();
2136 Distance lonSigma = aprioriPt.GetLonSigmaDistance();
2137 Distance radiusSigma = aprioriPt.GetLocalRadiusSigma();
2141 aprioriPt.SetSphericalSigmasDistance(latSigma, lonSigma, radiusSigma);
2151 catch (IException &e) {
2152 QString message =
"Unable to set Apriori Surface Point.\n";
2153 message +=
"Latitude = " + QString::number(lat);
2154 message +=
" Longitude = " + QString::number(lon);
2155 message +=
" Radius = " + QString::number(radius) +
"\n";
2156 message += e.toString();
2157 QMessageBox::critical(
this,
"Error",message);
2162 QString fullGroundFilename;
2170 m_editPoint->SetAprioriSurfacePointSourceFile(fullGroundFilename);
2227 emit cnetModified();
2259 QString message =
"The reference measure is Ignored. Unset the Ignore flag on the ";
2260 message +=
"reference measure before setting the point type to Constrained or Fixed.";
2261 QMessageBox::warning(
m_parent,
"Ignored Reference Measure", message);
2267 QString message =
"This control point is edit locked. The point type cannot be changed. You ";
2268 message +=
"must first unlock the point by clicking the check box above labeled ";
2269 message +=
"\"Edit Lock Point\".";
2270 QMessageBox::warning(
m_parent,
"Point Locked", message);
2285 for (
int i=0; i<
m_editPoint->GetNumMeasures(); i++) {
2287 if (m.GetChooserName() ==
"GroundMeasureTemporary") {
2342 QString message =
"Unable to change Ignored on point. Set EditLock ";
2343 message +=
" to False.";
2344 QMessageBox::critical(
this,
"Error", message);
2369 QMessageBox::warning(
this,
"Point Locked",
"Point is Edit Locked. You must un-lock point"
2370 " before changing a measure.");
2385 emit measureChanged();
2417 emit measureChanged();
2439 QMessageBox::warning(
this,
"Point Locked",
"Point is Edit Locked. You must un-lock point"
2440 " before changing a measure.");
2454 emit measureChanged();
2487 emit measureChanged();
2503 if (curIndex < m_rightCombo->count() - 1) {
2552 QString message =
"Make sure the correct cube is opened.\n\n";
2553 message += e.toString();
2554 QMessageBox::critical(
this,
"Error", message);
2601 QString message =
"Make sure the correct cube is opened.\n\n";
2602 message += e.toString();
2603 QMessageBox::critical(
this,
"Error", message);
2656 QString s =
"Reference: ";
2666 s =
"Measure Type: ";
2702 QString s =
"Reference: ";
2713 s =
"Measure Type: ";
2735 if(e->type() != QEvent::Leave)
return false;
2757 int r = QMessageBox::warning(
this, tr(
"OK to continue?"),
2758 tr(
"The currently opened registration template has been modified.\n"
2760 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2763 if (r == QMessageBox::Yes)
2765 else if (r == QMessageBox::Cancel)
2783 QString filename = QFileDialog::getOpenFileName(
this,
2784 "Select a registration template",
".",
2785 "Registration template files (*.def *.pvl);;All files (*)");
2787 if (filename.isEmpty())
2803 QFile file(
FileName((QString) fn).expanded());
2804 if (!file.open(QIODevice::ReadOnly)) {
2805 QString msg =
"Failed to open template file \"" + fn +
"\"";
2806 QMessageBox::warning(
this,
"IO Error", msg);
2810 QTextStream stream(&file);
2815 sb->setValue(sb->minimum());
2852 QString filename = QFileDialog::getSaveFileName(
this,
2853 "Save registration template",
".",
2854 "Registration template files (*.def *.pvl);;All files (*)");
2856 if (filename.isEmpty())
2880 QString message = e.toString();
2881 QMessageBox::warning(
this,
"Error", message);
2885 QString expandedFileName(
FileName((QString) fn).expanded());
2887 QFile file(expandedFileName);
2889 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2890 QString msg =
"Failed to save template file to \"" + fn +
"\"\nDo you "
2892 QMessageBox::warning(
this,
"IO Error", msg);
2897 QTextStream stream(&file);
2928 registrationDialog.setWindowTitle(
"View or Edit Template File: "
2929 + templatePvl.fileName());
2930 registrationDialog.resize(550,360);
2931 registrationDialog.exec();
2934 QString message = e.toString();
2935 QMessageBox::information(
this,
"Error", message);
2970 if(templateList->
type() ==
"registrations") {
2971 for(
int i = 0; i < templateList->size(); i++) {
2973 +
"/" +
FileName(templateList->at(i)->fileName()).
name());
2987 QString expandedFileName = filename;
2988 if(!filename.startsWith(
"$base")){
2990 +
"/registrations/" + filename;
3005 if(fileName.startsWith(
"$base")) {
3008 QList<QString> components = fileName.split(
"/");
3009 int size = components.size();
3010 int index =
m_templateComboBox->findText(components[size - 2] +
"/" + components[size - 1]);
3033 if (aprioriPoint.GetLatitude().degrees() ==
Null) {
3034 s =
"Apriori Latitude: Null";
3037 s =
"Apriori Latitude: " +
3038 QString::number(aprioriPoint.GetLatitude().degrees());
3040 m_aprioriLatitude->setText(s);
3041 if (aprioriPoint.GetLongitude().degrees() ==
Null) {
3042 s =
"Apriori Longitude: Null";
3045 s =
"Apriori Longitude: " +
3046 QString::number(aprioriPoint.GetLongitude().degrees());
3048 m_aprioriLongitude->setText(s);
3049 if (aprioriPoint.GetLocalRadius().meters() ==
Null) {
3050 s =
"Apriori Radius: Null";
3053 s =
"Apriori Radius: " +
3054 QString::number(aprioriPoint.GetLocalRadius().meters(),
'f',2) +
3057 m_aprioriRadius->setText(s);
3105 QColor qc = Qt::red;
3107 p.setColor(QPalette::ButtonText,qc);
3127 QColor qc = Qt::red;
3129 p.setColor(QPalette::ButtonText,qc);
3153 (
m_editPoint->GetReferenceSN() == serialNumber)) {
3158 return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
3192 void ControlPointEditWidget::showHelp() {
3195 helpDialog->setWindowTitle(
"Match Tool Help");
3197 QVBoxLayout *mainLayout =
new QVBoxLayout;
3198 helpDialog->setLayout(mainLayout);
3200 QLabel *matchTitle =
new QLabel(
"<h2>Match Tool</h2>");
3201 mainLayout->addWidget(matchTitle);
3203 QLabel *matchSubtitle =
new QLabel(
"A tool for interactively measuring and editing sample/line "
3204 "registration points between cubes. These "
3205 "points contain sample, line postions only, no latitude or "
3206 "longitude values are used or recorded.");
3207 matchSubtitle->setWordWrap(
true);
3208 mainLayout->addWidget(matchSubtitle);
3210 QTabWidget *tabArea =
new QTabWidget;
3211 tabArea->setDocumentMode(
true);
3212 mainLayout->addWidget(tabArea);
3215 QScrollArea *overviewTab =
new QScrollArea;
3216 overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3217 overviewTab->setWidgetResizable(
true);
3219 QVBoxLayout *overviewLayout =
new QVBoxLayout;
3220 overviewContainer->setLayout(overviewLayout);
3222 QLabel *purposeTitle =
new QLabel(
"<h2>Purpose</h2>");
3223 overviewLayout->addWidget(purposeTitle);
3225 QLabel *purposeText =
new QLabel(
"<p>This tool is for recording and editing registration "
3226 "points measured between cubes displayed in the <i>qview</i> main window.</p> <p>The "
3227 "recorded registration points are sample and line pixel coordinates only. Therefore, this "
3228 "tool can be used on any images including ones that do not contain a camera model "
3229 "(i.e, The existence of the Isis Instrument Group on the image labels is not required). "
3230 "This also means that the tool differs from the <i>qnet</i> control point network "
3231 "application in that no latitude or longitude values are ever used or recorded "
3232 "(regardless if the image has a camera model in Isis).</p>"
3233 "<p>The output control point network that this tool generates is primarily used 1) as "
3234 "input for an image-wide sample/line translation to register one image to another by "
3235 "'moving' pixel locations - refer to the documentation for applications such as "
3236 "<i>translate</i> and <i>warp</i>, or 2) to export the file and use the recorded "
3237 "measurements in other spreadsheet or plotting packages to visualize magnitude "
3238 "and direction of varying translations of the images relative to one another.</p> "
3239 "<p>An automated version of this match tool is the <i>coreg</i> application. This tool "
3240 "can be used to visually evaluate and edit the control point network created by "
3241 "<i>coreg</i>.</p> "
3242 "<p>The format of the output point network file is binary. This tool uses the Isis control "
3243 " network framework to create, co-register and save all control points and pixel "
3244 "measurements. The application <i>cnetbin2pvl</i> can be used to convert from binary to "
3245 "a readable PVL format."
3246 "<p>The Mouse Button functions are: (same as <i>qnet</i>)<ul><li>Modify Point=Left</li> "
3247 "<li>Delete Point=Middle</li><li>Create New Point=Right</li></ul></p>"
3248 "<p>Control Points are drawn on the associated displayed cubes with the following colors: "
3249 "Green=Valid registration point; Yellow=Ignored point; Red=Active point being edited");
3250 purposeText->setWordWrap(
true);
3251 overviewLayout->addWidget(purposeText);
3253 overviewTab->setWidget(overviewContainer);
3256 QScrollArea *quickTab =
new QScrollArea;
3257 quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3258 quickTab->setWidgetResizable(
true);
3260 QVBoxLayout *quickLayout =
new QVBoxLayout;
3261 quickContainer->setLayout(quickLayout);
3263 QLabel *quickTitle =
new QLabel(
"<h2>Quick Start</h2>");
3264 quickLayout->addWidget(quickTitle);
3266 QLabel *quickSubTitle =
new QLabel(
"<h3>Preparation:</h3>");
3267 quickLayout->addWidget(quickSubTitle);
3271 QLabel *quickPrep =
new QLabel(
"<p><ul>"
3272 "<li>Open the cubes with overlapping areas for choosing control points</li>"
3273 "<li>Choose the match tool <img src=\"" + toolIconDir +
3274 "/stock_draw-connector-with-arrows.png\" width=22 height=22> "
3275 "from the toolpad on the right side of the <i>qview</i> main window</li>");
3276 quickPrep->setWordWrap(
true);
3277 quickLayout->addWidget(quickPrep);
3279 QLabel *morePrep =
new QLabel(
"<p>Once the Match tool is activated the tool bar at the top "
3280 "of the main window contains file action buttons and a help button:");
3281 morePrep->setWordWrap(
true);
3282 quickLayout->addWidget(morePrep);
3284 QLabel *fileButtons =
new QLabel(
"<p><ul>"
3285 "<li><img src=\"" + toolIconDir +
"/fileopen.png\" width=22 height=22> Open an existing "
3286 "control network <b>Note:</b> If you do not open an existing network, a new one will "
3288 "<li><img src=\"" + toolIconDir +
"/mActionFileSaveAs.png\" width=22 height=22> Save "
3289 "control network as ...</li>"
3290 "<li><img src=\"" + toolIconDir +
"/mActionFileSave.png\" width=22 height=22> Save "
3291 "control network to current file</li>"
3292 "<li><img src=\"" + toolIconDir +
"/help-contents.png\" width=22 height=22> Show Help "
3294 fileButtons->setWordWrap(
true);
3295 quickLayout->addWidget(fileButtons);
3297 QLabel *quickFunctionTitle =
new QLabel(
"<h3>Cube Viewport Functions:</h3>");
3298 quickLayout->addWidget(quickFunctionTitle);
3300 QLabel *quickFunction =
new QLabel(
3301 "The match tool window will be shown once "
3302 "you click in a cube viewport window using one of the following "
3303 "mouse functions. <b>Note:</b> Existing control points are drawn on the cube viewports");
3304 quickFunction->setWordWrap(
true);
3305 quickLayout->addWidget(quickFunction);
3307 QLabel *quickDesc =
new QLabel(
"<p><ul>"
3308 "<li>Left Click - Modify the control point closest to the click <b>Note:</b> "
3309 "All cubes in the control point must be displayed before loading the point</li>"
3310 "<li>Middle Click - Delete the control point closest to the click</li>"
3311 "<li>Right Click - Create a new control point at the click location</li></ul></p>");
3312 quickDesc->setWordWrap(
true);
3313 quickDesc->setOpenExternalLinks(
true);
3314 quickLayout->addWidget(quickDesc);
3316 quickTab->setWidget(quickContainer);
3319 QScrollArea *controlPointTab =
new QScrollArea;
3320 controlPointTab->setWidgetResizable(
true);
3321 controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3323 QVBoxLayout *controlPointLayout =
new QVBoxLayout;
3324 controlPointContainer->setLayout(controlPointLayout);
3326 QLabel *controlPointTitle =
new QLabel(
"<h2>Control Point Editing</h2>");
3327 controlPointLayout->addWidget(controlPointTitle);
3329 QLabel *mouseLabel =
new QLabel(
"<p><h3>When the \"Match\" tool "
3330 "is activated, the mouse buttons have the following function in the "
3331 "cube viewports of the main qview window:</h3>");
3332 mouseLabel->setWordWrap(
true);
3333 mouseLabel->setScaledContents(
true);
3334 controlPointLayout->addWidget(mouseLabel);
3336 QLabel *controlPointDesc =
new QLabel(
"<ul>"
3337 "<li>Left click - Edit the closest control point <b>Note:</b> "
3338 "All cubes in the control point must be displayed before loading the point</li>"
3339 "<li>Middle click - Delete the closest control point</li>"
3340 "<li>Right click - Create new control point at cursor location. This will bring up a new "
3341 "point dialog which allows you to enter a point id and will list all cube viewports, "
3342 "highlighting cubes where the point has been chosen by clicking on the cube's viewport. "
3343 "When the desired cubes have been chosen, select the \"Done\" button which will load the "
3344 "control point into the control point editor window which will allow the control measure "
3345 "positions to be refined.</li>");
3346 controlPointDesc->setWordWrap(
true);
3347 controlPointLayout->addWidget(controlPointDesc);
3349 QLabel *controlPointEditing =
new QLabel(
3350 "<h4>Changing Control Measure Locations</h4>"
3351 "<p>Both the left and right control measure positions can be adjusted by:"
3353 "<li>Move the cursor location under the crosshair by clicking the left mouse "
3355 "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
3356 "<li>Move 1 pixel at a time by using arrow buttons above the right and left views</li>"
3358 "<h4>Other Point Editor Functions</h4>"
3359 "<p>Along the right border of the window:</p>"
3361 "<li><strong>Link Zoom</strong> This will link the two small viewports together when "
3362 "zooming (ie. If this is checked, if the left view is zoomed, the right view will "
3363 "match the left view's zoom factor. "
3364 "<b>Note:</b> Zooming is controlled from the left view.</li>"
3365 "<li><strong>No Rotate:</strong> Turn off the rotation and bring right view back to "
3366 "its original orientation</li>"
3367 "<li><strong>Rotate:</strong> Rotate the right view using either the dial "
3368 "or entering degrees </li>"
3369 "<li><strong>Show control points:</strong> Draw crosshairs at all control "
3370 "point locations visible within the view</li>"
3371 "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire "
3373 "<li><strong>Circle:</strong> Draw circle which may help center measure "
3374 "on a crater</li></ul"
3375 "<p>Below the left view:</p>"
3376 "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the "
3377 "left view window using the \"Blink Start\" button <img src=\"" + toolIconDir +
3378 "/blinkStart.png\" width=22 height=22> and \"Blink Stop\" button <img src=\"" +
3379 toolIconDir +
"/blinkStop.png\" width=22 height=22>. The arrow keys above the left "
3380 "and right views and the keyboard arrow keys may be used to move the both views while "
3382 "<li><strong>Register:</strong> Sub-pixel register the right view to "
3383 "the left view. A default registration template is used for setting parameters "
3384 "passed to the sub-pixel registration tool. The user may load in a predefined "
3385 "template or edit the current loaded template to influence successful "
3386 "co-registration results. For more information regarding the pattern matching "
3387 "functionlity or how to create a parameter template, refer to the Isis PatternMatch "
3388 "document and the <i>autoregtemplate</i> application.</li>"
3389 "<li><strong>Save Measures:</strong> Save the two control measures using the sample, "
3390 "line positions under the crosshairs.</li>"
3391 "<li><strong>Save Point:</strong> Save the control point to the control network.</li>"
3393 controlPointEditing->setWordWrap(
true);
3394 controlPointLayout->addWidget(controlPointEditing);
3396 controlPointTab->setWidget(controlPointContainer);
3398 tabArea->addTab(overviewTab,
"&Overview");
3399 tabArea->addTab(quickTab,
"&Quick Start");
3400 tabArea->addTab(controlPointTab,
"&Control Point Editing");
3402 QHBoxLayout *buttonsLayout =
new QHBoxLayout;
3404 buttonsLayout->addStretch();
3406 QPushButton *closeButton =
new QPushButton(
"&Close");
3407 closeButton->setIcon(QIcon(
FileName(
"$base/icons/guiStop.png").expanded()));
3408 closeButton->setDefault(
true);
3409 connect(closeButton, SIGNAL(clicked()),
3410 helpDialog, SLOT(close()));
3411 buttonsLayout->addWidget(closeButton);
3413 mainLayout->addLayout(buttonsLayout);
This is free and unencumbered software released into the public domain.
@ 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.
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.
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
@ 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
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.
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.
Project * project() const
Gets the Project for this directory.
Distance measurement, usually in meters.
@ Meters
The distance is being specified 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...
Dialog used by ControlPointEditWidget to select a new location for ground source files.
Buffer for containing a two dimensional section of an image.
static QString templateRoot(QString projectRoot)
Appends the root directory name 'templates' to the project .
QList< TemplateList * > regTemplates()
Return registration template FileNames.
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
Control * activeControl()
Return the Active Control (control network)
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.
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
Serial Number list generator.
void remove(const QString &sn)
Remove the specified serial number from the list.
QString serialNumber(const QString &filename)
Return a serial number given a filename.
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
int size() const
How many serial number / filename combos are in the list.
int serialNumberIndex(const QString &sn)
Return a list index given a serial number.
int fileNameIndex(const QString &filename)
Return a list index given a filename.
QString fileName(const QString &sn)
Return a filename given a serial number.
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.
This class defines a body-fixed surface point.
QString type() const
Get the type of template in this TemplateList.
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.