11#include <QInputDialog>
14#include <QStackedWidget>
16#include "AbstractPlotTool.h"
17#include "Application.h"
19#include "AutoRegFactory.h"
20#include "BundleAdjust.h"
21#include "ControlMeasure.h"
22#include "ControlNet.h"
23#include "ControlPoint.h"
24#include "ControlPointEdit.h"
25#include "CubePlotCurve.h"
29#include "IException.h"
34#include "MainWindow.h"
35#include "MdiCubeViewport.h"
38#include "ProfileDialog.h"
39#include "PvlEditDialog.h"
41#include "Projection.h"
42#include "QIsisApplication.h"
43#include "RubberBandTool.h"
44#include "SerialNumber.h"
46#include "SurfacePoint.h"
49#include "UniversalGroundMap.h"
66 QString StereoTool::lastPtIdValue =
"";
80 m_serialNumberList = NULL;
87 m_profileDialog = NULL;
95 connect(
this, SIGNAL( toolActivated() ),
this, SLOT( activateTool() ) );
106 m_stereoTool->setWindowTitle(
"Elevation Calculator (via stereo pairs)");
111 QGridLayout *gridLayout =
new QGridLayout();
115 gridLayout->setColumnMinimumWidth(0, 310);
116 gridLayout->setColumnMinimumWidth(1, 310);
120 m_ptIdValue =
new QLabel();
121 gridLayout->addWidget(m_ptIdValue, row++, 0);
123 m_leftCubeLabel =
new QLabel();
124 m_rightCubeLabel =
new QLabel();
125 gridLayout->addWidget(m_leftCubeLabel, row, 0);
126 gridLayout->addWidget(m_rightCubeLabel, row++, 1);
129 gridLayout->addWidget(m_pointEditor, row++, 0, 1, 3);
131 m_pointEditor->show();
137 m_elevationLabel =
new QLabel;
138 m_elevationLabel->setToolTip(
"Calculated elevation in meters.");
139 m_elevationLabel->setWhatsThis(
"Calculated elevation based on parallax.");
140 m_elevationErrorLabel =
new QLabel;
141 m_elevationErrorLabel->setToolTip(
142 "Error in calculated elevation in meters.");
143 m_elevationErrorLabel->setWhatsThis(
"Error in calculated elevation.");
144 gridLayout->addWidget(m_elevationLabel, row, 0);
145 gridLayout->addWidget(m_elevationErrorLabel, row++, 1);
147 m_baseRadiiLabel =
new QLabel;
148 m_baseRadiiLabel->setToolTip(
"Subtracted from the calculated radius to "
149 "determine elevation.");
151 m_leftDemRadiiLabel =
new QLabel;
152 m_leftDemRadiiLabel->setToolTip(
"Left Cube DEM Radius");
153 m_rightDemRadiiLabel =
new QLabel;
154 m_rightDemRadiiLabel->setToolTip(
"Right Cube DEM Radius");
155 gridLayout->addWidget(m_baseRadiiLabel, row, 0);
156 gridLayout->addWidget(m_leftDemRadiiLabel, row, 1);
157 gridLayout->addWidget(m_rightDemRadiiLabel, row++, 2);
165 cw->setLayout(gridLayout);
166 m_stereoTool->setCentralWidget(cw);
168 connect(
this, SIGNAL( editPointChanged() ),
this, SLOT(
paintAllViewports() ) );
180 m_save =
new QAction(m_stereoTool);
181 m_save->setText(
"Save Elevation Data...");
183 "<b>Function:</b> Saves the elevation calulations to current file.";
184 m_save->setWhatsThis(whatsThis);
185 connect( m_save, SIGNAL( triggered() ),
this, SLOT( saveElevations() ) );
186 m_save->setDisabled(
true);
189 saveAs->setText(
"Save Elevation Data As...");
191 "<b>Function:</b> Saves the elevation calulations to a file.";
192 saveAs->setWhatsThis(whatsThis);
196 closeStereoTool->setText(
"&Close");
197 closeStereoTool->setShortcut(Qt::ALT + Qt::Key_F4);
199 "<b>Function:</b> Closes the Stereo Tool window for this point \
200 <p><b>Shortcut:</b> Alt+F4 </p>";
201 closeStereoTool->setWhatsThis(whatsThis);
202 connect( closeStereoTool, SIGNAL( triggered() ), m_stereoTool, SLOT( close() ) );
204 QMenu *fileMenu = m_stereoTool->menuBar()->addMenu(
"&File");
205 fileMenu->addAction(m_save);
206 fileMenu->addAction(saveAs);
207 fileMenu->addAction(closeStereoTool);
210 templateFile->setText(
"&Set registration template");
212 "<b>Function:</b> Allows user to select a new file to set as the registration template";
213 templateFile->setWhatsThis(whatsThis);
214 connect( templateFile, SIGNAL( triggered() ),
this, SLOT(
setTemplateFile() ) );
217 viewTemplate->setText(
"&View/edit registration template");
219 "<b>Function:</b> Displays the curent registration template. \
220 The user may edit and save changes under a chosen filename.";
221 viewTemplate->setWhatsThis(whatsThis);
222 connect( viewTemplate, SIGNAL( triggered() ),
this, SLOT(
viewTemplateFile() ) );
225 QMenu *optionMenu = m_stereoTool->menuBar()->addMenu(
"&Options");
226 QMenu *regMenu = optionMenu->addMenu(
"&Registration");
228 regMenu->addAction(templateFile);
229 regMenu->addAction(viewTemplate);
232 QAction *showHelpAct =
new QAction(
"stereo tool &Help", m_stereoTool);
233 showHelpAct->setIcon(QPixmap(
toolIconDir() +
"/help-contents.png") );
234 connect( showHelpAct, SIGNAL( triggered() ),
this, SLOT( showHelp() ));
236 QMenu *helpMenu = m_stereoTool->menuBar()->addMenu(
"&Help");
237 helpMenu->addAction(showHelpAct);
252 action->setIcon( QPixmap(
toolIconDir() +
"/3d-glasses-icon.png") );
253 action->setToolTip(
"Stereo");
254 action->setWhatsThis(
"<strong>Functionality:</strong> "
256 "<li>Calculate elevation at a single point by creating a "
257 "control point between the image pair. "
259 "<h4><strong>Control Point mouse Button Functions:</strong></h4>"
260 "<li>Left: Edit closest point.</li>"
261 "<li>Middle: Delete closest point.</li>"
262 "<li>Right: Create new point at cursor position.</li></ul>"
263 "<li>Left click and drag will create an elevation profile "
264 "after you create the start and end control points. A dialog "
265 "box will be shown to assist.</li>"
266 "<li>Right click and drag will create an elevation profile "
267 "between previously created control points.</li></ul>");
283 QLabel *boxLabel =
new QLabel(
"Local Radius:");
285 m_radiusBox->addItem(
"Ellipsoid Equitorial Radius");
286 m_radiusBox->addItem(
"DEM Radius");
287 m_radiusBox->addItem(
"Custom Radius");
288 m_radiusBox->setToolTip(
"Source for local radius");
290 "<b>Function: </b>Source for the local radius used for elevation "
292 m_radiusBox->setWhatsThis(text);
293 connect( m_radiusBox, SIGNAL( activated(
int) ),
294 this, SLOT( updateRadiusLineEdit() ));
296 m_radiusLineEdit =
new QLineEdit(hbox);
297 QDoubleValidator *dval =
new QDoubleValidator(hbox);
298 m_radiusLineEdit->setValidator(dval);
299 m_radiusLineEdit->setReadOnly(
true);
300 m_radiusLineEdit->setToolTip(
"Custom local radius used for elevation "
301 "calculations. To enter a value, set box to "
302 "the left to \"Custom Radius\"");
304 "<b>Function: </b>Custom local radius used to calculate elevations. "
305 "This can be changed by selecting \"Custom Radius\" in the box to "
307 m_radiusLineEdit->setWhatsThis(text);
310 connect( m_radiusLineEdit, SIGNAL( editingFinished() ),
311 this, SLOT( userBaseRadius() ));
313 m_radiusLineEdit->setEnabled(
false);
315 QLabel *radiusUnit =
new QLabel(
"Meters");
317 QToolButton *helpButton =
new QToolButton(hbox);
318 helpButton->setIcon( QPixmap(
toolIconDir() +
"/help-contents.png") );
319 helpButton->setToolTip(
"Help");
320 helpButton->setIconSize( QSize(22, 22) );
321 connect( helpButton, SIGNAL( clicked() ),
this, SLOT( showHelp() ));
323 QHBoxLayout *layout =
new QHBoxLayout;
324 layout->setMargin(0);
326 layout->addWidget(boxLabel);
327 layout->addWidget(m_radiusBox);
328 layout->addWidget(m_radiusLineEdit);
329 layout->addWidget(radiusUnit);
330 layout->addStretch();
331 layout->addWidget(helpButton);
332 hbox->setLayout(layout);
341 void StereoTool::activateTool() {
351 qobject_cast<QWidget *>( parent() ) );
362 void StereoTool::warningDialog() {
367 QVBoxLayout *mainLayout =
new QVBoxLayout;
368 warningDialog->setLayout(mainLayout);
370 QLabel *warningsText =
new QLabel(
"<p><strong>Warning:</strong> "
371 "The camera orientations are very critical for correct results. "
372 "Poor orientations will result in bad elevation measurements. The "
373 "camera orientations can be corrected with the programs "
374 "<i>jigsaw, deltack, or qtie.");
375 warningsText->setWordWrap(
true);
376 mainLayout->addWidget(warningsText);
377 QCheckBox *showWarning =
new QCheckBox(
"Do not show this message again");
378 showWarning->setChecked(
false);
379 mainLayout->addWidget(showWarning);
381 QPushButton *okButton =
new QPushButton(
"OK");
382 mainLayout->addStretch();
383 mainLayout->addWidget(okButton);
384 connect( okButton, SIGNAL( clicked() ), warningDialog, SLOT( accept() ));
386 if ( warningDialog->exec() ) {
387 if ( showWarning->isChecked() ) m_showWarning =
false;
396 void StereoTool::showHelp() {
399 helpDialog->setWindowTitle(
"Stereo Tool Help");
401 QVBoxLayout *mainLayout =
new QVBoxLayout;
402 helpDialog->setLayout(mainLayout);
404 QLabel *stereoTitle =
new QLabel(
"<h2>Stereo Tool</h2>");
405 mainLayout->addWidget(stereoTitle);
407 QLabel *stereoSubtitle =
new QLabel(
"A tool for calculating point elevations "
408 "and elevation profiles using stereo pairs "
410 stereoSubtitle->setWordWrap(
true);
411 mainLayout->addWidget(stereoSubtitle);
413 QTabWidget *tabArea =
new QTabWidget;
414 tabArea->setDocumentMode(
true);
415 mainLayout->addWidget(tabArea);
418 QScrollArea *overviewTab =
new QScrollArea;
419 overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
420 overviewTab->setWidgetResizable(
true);
422 QVBoxLayout *overviewLayout =
new QVBoxLayout;
423 overviewContainer->setLayout(overviewLayout);
425 QLabel *purposeTitle =
new QLabel(
"<h2>Purpose</h2>");
426 overviewLayout->addWidget(purposeTitle);
428 QLabel *purposeText =
new QLabel(
"<p>This tool will use parallax from a "
429 "stereo pair of cubes to calculate elevations at chosen control points "
430 "or create elevation profiles between two chosen control points. "
431 "Elevations are computed from points between the left and right cubes. "
432 "Vectors from the target (planet center) to the spacecraft and target "
433 "to the surface registration points are computed for each point. From "
434 "these points, the elevation is computed.");
435 purposeText->setWordWrap(
true);
436 overviewLayout->addWidget(purposeText);
438 QLabel *warningsTitle =
new QLabel(
"<h2>Warnings</h2>");
439 overviewLayout->addWidget(warningsTitle);
441 QLabel *warningsText =
new QLabel(
"<p>The camera orientations are very "
442 "critical for correct results. Poor orientations will result in "
443 "bad elevation measurements. The camera orientations can be corrected "
444 "with the programs <i>jigsaw, deltack, or qtie.");
445 warningsText->setWordWrap(
true);
446 overviewLayout->addWidget(warningsText);
448 overviewTab->setWidget(overviewContainer);
451 QScrollArea *quickTab =
new QScrollArea;
452 quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
453 quickTab->setWidgetResizable(
true);
455 QVBoxLayout *quickLayout =
new QVBoxLayout;
456 quickContainer->setLayout(quickLayout);
458 QLabel *quickTitle =
new QLabel(
"<h2>Quick Start</h2>");
459 quickLayout->addWidget(quickTitle);
461 QLabel *quickSubTitle =
new QLabel(
"<h3>Preparation:</h3>");
462 quickLayout->addWidget(quickSubTitle);
464 QLabel *quickPrep =
new QLabel(
"<p><ul>"
465 "<li>Open the two cubes of a stereo pair</li>"
466 "<li>Link the two displayed cube windows</li>");
467 quickPrep->setWordWrap(
true);
468 quickLayout->addWidget(quickPrep);
470 QLabel *quickFunctionTitle =
new QLabel(
"<h3>Cube Viewport Functions:</h3>");
471 quickLayout->addWidget(quickFunctionTitle);
473 QLabel *quickFunction =
new QLabel(
474 "The stereo tool window will be shown once "
475 "you click on a cube viewport window using one of the following "
476 "cube viewport functions.");
477 quickFunction->setWordWrap(
true);
478 quickLayout->addWidget(quickFunction);
480 QLabel *quickDesc =
new QLabel(
"<p><ul>"
481 "<li>Calculate elevation at a single point by creating a "
482 "control point between the image pair by right clicking in the cube "
483 "viewport window on the location you are interested in. Once the "
484 "control point is refined, click the \"Save Measure\" button in "
485 "the Stereo Tool window and the elevation will be calculated. The elevation "
486 "reported is relative to the radius which is defined on the toolbar.</li>"
487 "<li>Left click and drag will create an elevation profile "
488 "after you create the start and end control points. A dialog "
489 "box will be shown to assist in creating the control points.</li>"
490 "<li>Right click and drag will create an elevation profile "
491 "between two previously created control points.</li></ul>"
492 "<p><strong>Note:</strong> The quality of the profiles is dependent on the registration "
493 "between the two images at each point along the profile. Registration "
494 "parameters can be changed under Options->Registration mentu of the "
495 "Elevation Calculator window. A discussion of these parameters can be found at: "
496 "<a href=\"http://isis.astrogeology.usgs.gov/documents/PatternMatch/PatternMatch.html\">"
497 "Pattern Matching</a>");
498 quickDesc->setWordWrap(
true);
499 quickDesc->setOpenExternalLinks(
true);
500 quickLayout->addWidget(quickDesc);
502 quickTab->setWidget(quickContainer);
505 QScrollArea *controlPointTab =
new QScrollArea;
506 controlPointTab->setWidgetResizable(
true);
507 controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
509 QVBoxLayout *controlPointLayout =
new QVBoxLayout;
510 controlPointContainer->setLayout(controlPointLayout);
512 QLabel *controlPointTitle =
new QLabel(
"<h2>Control Point Editing</h2>");
513 controlPointLayout->addWidget(controlPointTitle);
515 QLabel *mouseLabel =
new QLabel(
"<p><h3>When the \"Stereo\" tool "
516 "is activated, the mouse buttons have the following function in the "
517 "cube viewports of the main qview window:</h3>");
518 mouseLabel->setWordWrap(
true);
519 mouseLabel->setScaledContents(
true);
520 controlPointLayout->addWidget(mouseLabel);
522 QLabel *controlPointDesc =
new QLabel(
"<ul>"
523 "<li>Left click - Edit the closest control point</li>"
524 "<li>Middle click - Delete the closest control point</li>"
525 "<li>Right click - Create new control point at cursor location</li>"
526 "<li>Left click and drag - Create an elevation profile "
527 "after you create the start and end control points. A dialog "
528 "box will be shown to assist in creating the control points.</li>"
529 "<li>Right click and drag - Create an elevation profile "
530 "between two previously created control points.</li></ul>");
531 controlPointDesc->setWordWrap(
true);
532 controlPointLayout->addWidget(controlPointDesc);
534 QLabel *controlPointEditing =
new QLabel(
535 "<h4>Changing Measure Locations</h4>"
536 "<p>The measure location can be adjusted by:"
538 "<li>Move the cursor location under the crosshair by clicking the left mouse "
540 "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
541 "<li>Move 1 pixel at a time by using arrow buttons above the right view</li>"
543 "<h4>Other Point Editor Functions</h4>"
544 "<p>Along the right border of the window:</p>"
546 "<li><strong>Geom:</strong> Geometrically match the right view to the left"
548 "<li><strong>Rotate:</strong> Rotate the right view using either the dial"
549 "or entering degrees </li>"
550 "<li><strong>Show control points:</strong> Draw crosshairs at all control"
551 "point locations visible within the view</li>"
552 "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire"
554 "<li><strong>Circle:</strong> Draw circle which may help center measure"
555 "on a crater</li></ul"
556 "<p>Below the left view:</p>"
557 "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the"
558 "left view window using the \"Blink Start\" button (with play icon) and "
559 "\"Blink Stop\" button (with stop icon). Both arrow keys above the right view "
560 "and the keyboard arrow keys may be used to move the right view while"
562 "<li><strong>Find:</strong> Center the right view so that the same latitude "
563 "longitude is under the crosshair as the left view.</li></ul"
564 "<p>Below the right view:</p>"
565 "<ul><li><strong>Register:</strong> Sub-pixel register the the right view to"
566 "the left view.</li>"
567 "<li><strong>Save Measure:</strong> Save the control point under the"
568 "crosshairs and calculated elevation.</li></ul>");
569 controlPointEditing->setWordWrap(
true);
570 controlPointLayout->addWidget(controlPointEditing);
572 controlPointTab->setWidget(controlPointContainer);
576 tabArea->addTab(overviewTab,
"&Overview");
577 tabArea->addTab(quickTab,
"&Quick Start");
578 tabArea->addTab(controlPointTab,
"&Control Point Editing");
580 QHBoxLayout *buttonsLayout =
new QHBoxLayout;
582 buttonsLayout->addStretch();
584 QPushButton *closeButton =
new QPushButton(
"&Close");
585 closeButton->setIcon( QPixmap(
toolIconDir() +
"/guiStop.png" ) );
586 closeButton->setDefault(
true);
587 connect( closeButton, SIGNAL( clicked() ),
588 helpDialog, SLOT( close() ) );
589 buttonsLayout->addWidget(closeButton);
591 mainLayout->addLayout(buttonsLayout);
600 void StereoTool::userBaseRadius() {
603 m_baseRadius =
Distance(m_radiusLineEdit->text().toDouble(),
608 if (m_stereoTool->isVisible() && m_editPoint != NULL) {
609 calculateElevation();
613 QString message =
"Invalid base radius entered.";
614 message += e.toString();
615 m_radiusLineEdit->setText(
"");
616 QMessageBox::critical(m_stereoTool,
"Error", message);
625 void StereoTool::updateRadiusLineEdit() {
628 if ( m_radiusBox->currentText() ==
"Ellipsoid Equitorial Radius" ) {
629 if ( m_targetRadius.
isValid() ) {
630 m_radiusLineEdit->setText( QString::number( m_targetRadius.
meters(),
'f',
632 m_baseRadius = m_targetRadius;
635 m_radiusLineEdit->setText(
"");
637 m_radiusLineEdit->setReadOnly(
true);
638 m_radiusLineEdit->setEnabled(
false);
640 else if ( m_radiusBox->currentText() ==
"DEM Radius" ) {
644 if ( m_leftCube->
camera()->
target()->shape()->name() ==
"Ellipsoid" ) {
645 QString message =
"No valid Dem on cube. Run <i>spicinit</i> using a "
646 "dem shape model. The local radius will default back to the ellipsoid.";
647 QMessageBox::warning(m_stereoTool,
"Warning", message);
648 m_radiusBox->setCurrentIndex(0);
650 m_radiusLineEdit->setReadOnly(
true);
651 m_radiusLineEdit->setEnabled(
false);
655 m_radiusLineEdit->setText(
"");
656 m_radiusLineEdit->setReadOnly(
true);
657 m_radiusLineEdit->setEnabled(
false);
661 m_radiusLineEdit->setReadOnly(
false);
662 m_radiusLineEdit->setEnabled(
true);
666 if ( m_stereoTool->isVisible() && m_editPoint != NULL ) {
667 calculateElevation();
673 void StereoTool::setupFiles() {
683 m_linkedViewports.clear();
689 if ( m_linkedViewports.size() < 2 ) {
690 IString message =
"Two cube viewports containing a stereo pair "
691 "need to be linked.";
694 if ( m_linkedViewports.size() > 2 ) {
695 IString message =
"Only two cube viewports containing a stereo pair "
702 if ( m_linkedViewports.at(0)->cube() == m_leftCube ||
703 m_linkedViewports.at(0)->cube() == m_rightCube ) {
704 if ( m_linkedViewports.at(1)->cube() == m_leftCube ||
705 m_linkedViewports.at(1)->cube() == m_rightCube ) {
713 if ( m_controlNet->GetTarget() !=
714 m_linkedViewports.at(0)->cube()->camera()->target()->name() ) {
717 QString message =
"You have changed targets. All data must be re-set";
718 message +=
" for new target. Would you like to save your current";
719 message +=
" points before resetting?";
720 int response = QMessageBox::question(m_stereoTool,
721 "Save current points", message,
722 QMessageBox::Yes | QMessageBox::No,
724 if (response == QMessageBox::Yes) {
727 m_stereoTool->setVisible(
false);
730 m_controlNet->SetTarget(*m_linkedViewports.at(0)->cube()->label());
736 m_controlNet->SetTarget(
737 m_linkedViewports.at(0)->cube()->camera()->target()->name() );
745 setFiles( m_linkedViewports.at(0)->cube(), m_linkedViewports.at(1)->cube() );
761 m_stereoTool->setVisible(
false);
786 m_leftCube = leftCube;
787 m_rightCube = rightCube;
792 m_leftCubeLabel->setText(leftName);
793 m_rightCubeLabel->setText(rightName);
803 m_serialNumberList->
add( m_rightCube->
fileName() );
811 QString message =
"Could not determine target radius.";
812 QMessageBox::critical(m_stereoTool,
"Error",message);
814 updateRadiusLineEdit();
817 updateRadiusLineEdit();
824 QString message =
"Cannot initialize universal ground map for " +
826 message += e.toString();
827 QMessageBox::critical(m_stereoTool,
"Error", message);
834 QString message =
"Cannot initialize universal ground map for" +
836 message += e.toString();
837 QMessageBox::critical(m_stereoTool,
"Error", message);
852 double samp = m_editPoint->
GetMeasure(Left)->GetSample();
853 double line = m_editPoint->
GetMeasure(Left)->GetLine();
866 QString message =
"Unable to set Apriori Surface Point.\n";
867 message +=
"Latitude = " + QString::number(lat);
868 message +=
" Longitude = " + QString::number(lon);
869 message +=
" Radius = " + QString::number(m_targetRadius.
meters(),
'f',
871 message += e.toString();
872 QMessageBox::critical(m_stereoTool,
"Error", message);
875 calculateElevation();
876 emit editPointChanged();
887 rubberBandTool()->
enable(RubberBandTool::LineMode);
888 rubberBandTool()->enablePoints();
889 rubberBandTool()->enableAllClicks();
895 void StereoTool::rubberBandComplete() {
903 QString message = e.toString();
904 QMessageBox::critical(m_stereoTool,
"Error setting stereo pair", message);
905 rubberBandTool()->
clear();
913 QString file = cvp->cube()->fileName();
919 QString message =
"This cube is not linked as a stereo pair. Make ";
920 message +=
"sure you have two stereo pair cube viewports linked.";
921 QMessageBox::critical(m_stereoTool,
"Viewport not linked", message);
925 if ( rubberBandTool()->figureIsPoint() ) {
927 cvp->viewportToCube( rubberBandTool()->vertices()[0].rx(),
928 rubberBandTool()->vertices()[0].ry(),
930 if ( rubberBandTool()->mouseButton() & Qt::LeftButton ) {
931 if ( !m_controlNet || m_controlNet->GetNumMeasures() == 0 ) {
932 QString message =
"No points exist for editing. Create points ";
933 message +=
"using the right mouse button.";
934 QMessageBox::information(m_stereoTool,
"Warning", message);
940 point = m_controlNet->FindClosest(sn, samp, line);
943 QString message =
"No points found for editing. Create points ";
944 message +=
"using the right mouse button.";
945 message += e.toString();
946 QMessageBox::critical(m_stereoTool,
"Error", message);
951 else if ( rubberBandTool()->mouseButton() & Qt::MiddleButton ) {
952 if ( !m_controlNet || m_controlNet->GetNumPoints() == 0 ) {
953 QString message =
"No points exist for deleting. Create points ";
954 message +=
"using the right mouse button.";
955 QMessageBox::warning(m_stereoTool,
"Warning", message);
961 m_controlNet->FindClosest(sn, samp, line);
964 QString message =
"No points exist for deleting. Create points ";
965 message +=
"using the right mouse button.";
966 QMessageBox::information(m_stereoTool,
"Warning", message);
971 else if ( rubberBandTool()->mouseButton() & Qt::RightButton ) {
973 if (cvp->cube() == m_leftCube) {
987 QString message =
"Cannot create control point.\n\n";
988 message += e.toString();
989 QMessageBox::critical(m_stereoTool,
"Error", message);
991 rubberBandTool()->
clear();
1001 if ( rubberBandTool()->mouseButton() & Qt::RightButton ) {
1003 cvp->viewportToCube( rubberBandTool()->vertices()[0].rx(),
1004 rubberBandTool()->vertices()[0].ry(),
1007 m_startPoint = m_controlNet->FindClosest(sn, samp, line);
1010 QString message =
"Cannot find start point for profile. Either ";
1011 message +=
"create end points individually using the right mouse ";
1012 message +=
"button. Or, create profile end points by clicking and ";
1013 message +=
"dragging with the right mouse button.\n\n";
1014 message += e.toString();
1015 QMessageBox::critical(m_stereoTool,
"Error", message);
1016 m_startPoint = NULL;
1017 rubberBandTool()->
clear();
1020 cvp->viewportToCube( rubberBandTool()->vertices()[1].rx(),
1021 rubberBandTool()->vertices()[1].ry(),
1024 m_endPoint = m_controlNet->FindClosest(sn, samp, line);
1025 if ( m_startPoint->
GetId() == m_endPoint->
GetId() ) {
1031 QString message =
"Cannot find end point for profile. Either ";
1032 message +=
"create end points individually using the right mouse ";
1033 message +=
"button. Or, create profile end points by clicking and ";
1034 message +=
"dragging with the right mouse button.\n\n";
1035 message += e.toString();
1036 QMessageBox::critical(m_stereoTool,
"Error", message);
1037 m_startPoint = NULL;
1039 rubberBandTool()->
clear();
1047 connect( m_profileDialog, SIGNAL( createStart() ),
1048 this, SLOT( createStartPoint() ) );
1049 connect( m_profileDialog, SIGNAL( createEnd() ),
1050 this, SLOT( createEndPoint() ) );
1051 connect( m_profileDialog, SIGNAL( accepted() ),
1052 this, SLOT( profile() ) );
1053 connect( m_profileDialog, SIGNAL( accepted() ),
1054 this, SLOT( profile() ) );
1055 connect( m_profileDialog, SIGNAL( rejected() ),
1056 this, SLOT( clearProfile() ) );
1057 m_profileDialog->show();
1058 m_profileDialog->activateWindow();
1065 void StereoTool::clearProfile() {
1066 m_startPoint = NULL;
1068 rubberBandTool()->
clear();
1069 delete m_profileDialog;
1070 m_profileDialog = NULL;
1075 void StereoTool::createStartPoint() {
1082 cvp->viewportToCube( rubberBandTool()->vertices()[0].rx(),
1083 rubberBandTool()->vertices()[0].ry(),
1085 if ( cvp->cube() == m_leftCube ) {
1099 QString message =
"Cannot create control point.\n\n";
1100 message += e.toString();
1101 QMessageBox::critical(m_stereoTool,
"Error", message);
1102 delete m_profileDialog;
1103 m_profileDialog = NULL;
1104 rubberBandTool()->
clear();
1107 m_startPoint = m_editPoint;
1112 void StereoTool::createEndPoint() {
1119 cvp->viewportToCube( rubberBandTool()->vertices()[1].rx(),
1120 rubberBandTool()->vertices()[1].ry(),
1122 if ( cvp->cube() == m_leftCube ) {
1136 QString message =
"Cannot create control point.\n\n";
1137 message += e.toString();
1138 QMessageBox::critical(m_stereoTool,
"Error", message);
1139 m_startPoint = NULL;
1140 delete m_profileDialog;
1141 m_profileDialog = NULL;
1142 rubberBandTool()->
clear();
1145 m_endPoint = m_editPoint;
1167 double leftSamp = 0, leftLine = 0;
1168 double rightSamp = 0, rightLine = 0;
1172 leftSamp = m_leftGM->
Sample();
1173 leftLine = m_leftGM->
Line();
1178 rightSamp = m_rightGM->
Sample();
1179 rightLine = m_rightGM->
Line();
1180 if ( rightSamp < 1 || rightSamp > m_rightCube->
sampleCount() ||
1181 rightLine < 1 || rightLine > m_rightCube->
lineCount() ) {
1182 IString message =
"Point does not exist on cube, " +
1192 IString message =
"Point does not exist on cube, " +
1202 IString message =
"Point does not exist on cube, " +
1214 bool goodId =
false;
1217 QString
id = QInputDialog::getText(m_stereoTool,
1218 "Point ID",
"Enter Point ID:",
1219 QLineEdit::Normal, lastPtIdValue,
1226 if ( ok &&
id.isEmpty() ) {
1228 QString message =
"You must enter a point Id.";
1229 QMessageBox::warning(m_stereoTool,
"Warning", message);
1234 if ( m_controlNet->GetNumPoints() > 0 &&
1235 m_controlNet->ContainsPoint(newPoint->
GetId() ) ) {
1236 QString message =
"A ControlPoint with Point Id = [" +
1238 "] already exists. Re-enter unique Point Id.";
1239 QMessageBox::warning(m_stereoTool,
"Unique Point Id", message);
1256 mLeft->SetCoordinate(leftSamp, leftLine);
1258 mLeft->SetDateTime();
1260 newPoint->
Add(mLeft);
1264 mRight->SetCoordinate(rightSamp, rightLine);
1266 mRight->SetDateTime();
1268 newPoint->
Add(mRight);
1271 m_controlNet->AddPoint(newPoint);
1273 m_editPoint = m_controlNet->GetPoint( (QString) newPoint->
GetId() );
1276 m_stereoTool->setVisible(
true);
1277 m_stereoTool->raise();
1279 emit editPointChanged();
1296 m_editPoint = point;
1299 emit editPointChanged();
1303 m_controlNet->DeletePoint( m_editPoint->
GetId() );
1304 m_stereoTool->setVisible(
false);
1307 emit editPointChanged();
1319 m_editPoint = point;
1321 m_stereoTool->setVisible(
true);
1322 m_stereoTool->raise();
1323 emit editPointChanged();
1336 m_editPoint->
GetId() );
1338 m_rightCube, m_editPoint->
GetId() );
1341 QString ptId =
"Point ID: " + m_editPoint->
GetId();
1342 m_ptIdValue->setText(ptId);
1350 QString serialNumber) {
1355 vp->cubeToViewport( m_startPoint->
GetMeasure(serialNumber)->GetSample(),
1356 m_startPoint->
GetMeasure(serialNumber)->GetLine(),
1358 vp->cubeToViewport( m_endPoint->
GetMeasure(serialNumber)->GetSample(),
1359 m_endPoint->
GetMeasure(serialNumber)->GetLine(),
1361 painter->setPen(Qt::green);
1362 painter->drawLine(x1, y1, x2, y2);
1380 if ( m_controlNet == NULL || m_controlNet->GetNumPoints() == 0 )
1386 if ( !m_controlNet->GetCubeSerials().contains(
1387 serialNumber) )
return;
1395 QList<ControlMeasure *> measures =
1396 m_controlNet->GetMeasuresInCube(serialNumber);
1398 for (
int i = 0; i < measures.count(); i++) {
1401 double samp = m->GetSample();
1402 double line = m->GetLine();
1404 vp->cubeToViewport(samp, line, x, y);
1406 if ( m->Parent()->IsIgnored() ) {
1407 painter->setPen( QColor(255, 255, 0) );
1410 else if ( m->IsIgnored() ) {
1411 painter->setPen( QColor(255, 255, 0) );
1415 painter->setPen(Qt::magenta);
1418 painter->setPen(Qt::green);
1421 painter->drawLine(x - 5, y, x + 5, y);
1422 painter->drawLine(x, y - 5, x, y + 5);
1426 if ( m_editPoint != NULL ) {
1430 double samp = (*m_editPoint)[serialNumber]->GetSample();
1431 double line = (*m_editPoint)[serialNumber]->GetLine();
1433 vp->cubeToViewport(samp, line, x, y);
1435 QBrush brush(Qt::red);
1439 painter->setPen(pen);
1440 painter->drawLine(x - 5, y, x + 5, y);
1441 painter->drawLine(x, y - 5, x, y + 5);
1461 vp->viewport()->update();
1467 void StereoTool::calculateElevation() {
1468 calculateElevation(m_editPoint);
1479 double elevation=0., elevationError=0.;
1485 if ( m_radiusBox->currentText() ==
"DEM Radius" ) {
1487 leftCamera->SetImage( (*point)[Left]->GetSample(),
1488 (*point)[Left]->GetLine() );
1489 m_baseRadius = leftCamera->LocalRadius( leftCamera->GetLatitude(),
1490 leftCamera->GetLongitude() );
1491 if ( !m_baseRadius.
isValid() ) {
1492 QString message =
"Invalid Dem radius, defaulting to ellipsoidal.";
1493 QMessageBox::warning(m_stereoTool,
"Invalid Dem radius", message);
1494 m_baseRadius = m_targetRadius;
1498 leftCamera->IgnoreElevationModel(
true);
1499 leftCamera->SetImage( (*point)[Left]->GetSample(),
1500 (*point)[Left]->GetLine() );
1503 rightCamera->SetImage( (*point)[Right]->GetSample(),
1504 (*point)[Right]->GetLine() );
1506 double radius, lat, lon, sepang;
1507 if ( Stereo::elevation( *leftCamera, *rightCamera, radius, lat, lon, sepang,
1508 elevationError ) ) {
1509 elevation = radius - m_baseRadius.
meters();
1512 leftCamera->IgnoreElevationModel(
false);
1513 rightCamera->IgnoreElevationModel(
false);
1518 point->
GetMeasure(Left)->SetFocalPlaneMeasured(elevation, elevationError);
1535 QString filename = QFileDialog::getOpenFileName( m_stereoTool,
1536 "Select a registration template",
".",
1537 "Registration template files (*.def *.pvl);;All files (*)" );
1539 if ( filename.isEmpty() )
1561 Pvl templatePvl( m_pointEditor->templateFileName() );
1565 registrationDialog.setWindowTitle(
"View or Edit Template File: "
1566 + templatePvl.fileName() );
1567 registrationDialog.resize(550, 360);
1568 registrationDialog.exec();
1571 QString message = e.toString();
1572 QMessageBox::warning(m_stereoTool,
"Error", message);
1584 QString fn = QFileDialog::getSaveFileName( m_stereoTool,
1585 "Choose filename to save under",
1587 "CSV Files (*.csv)" );
1591 if ( !fn.isEmpty() ) {
1592 if ( !fn.endsWith(
".csv") ) {
1593 filename = fn +
".csv";
1604 m_currentFile.setFileName(filename);
1606 m_save->setEnabled(
true);
1612 void StereoTool::saveElevations() {
1614 if ( m_currentFile.fileName().isEmpty() )
return;
1616 bool success = m_currentFile.open(QIODevice::WriteOnly);
1618 QMessageBox::critical(m_stereoTool,
"Error",
1619 "Cannot open file, please check permissions");
1620 m_currentFile.setFileName(
"");
1621 m_save->setDisabled(
true);
1625 QTextStream text(&m_currentFile);
1626 QString header =
"Point ID, Latitude, Longitude, Radius, ";
1627 header +=
"Elevation, Elevation Error, ";
1628 header +=
"Image 1, Sample, Line, Image 2, Sample, Line";
1629 text << header << Qt::endl;
1634 for (
int i = 0; i < m_controlNet->GetNumPoints(); i++) {
1637 data = p.GetId() +
"," +
1638 QString::number( apriori.GetLatitude().degrees() ) +
"," +
1639 QString::number( apriori.GetLongitude().degrees() ) +
"," +
1640 QString::number( p.GetMeasure(Left)->GetDiameter(),
'f', 6 ) +
1642 QString::number( p.GetMeasure(Left)->GetFocalPlaneMeasuredX(),
'f',
1644 QString::number( p.GetMeasure(Left)->GetFocalPlaneMeasuredY(),
'f',
1645 6 ) +
"," + leftFile +
"," +
1646 QString::number( p.GetMeasure(Left)->GetSample() ) +
"," +
1647 QString::number( p.GetMeasure(Left)->GetLine() ) +
"," +
1649 QString::number( p.GetMeasure(Right)->GetSample() ) +
"," +
1650 QString::number( p.GetMeasure(Right)->GetLine() );
1651 text << data << Qt::endl;
1653 m_currentFile.close();
1659 void StereoTool::clearNetData() {
1661 delete m_controlNet;
1662 m_controlNet = NULL;
1663 delete m_serialNumberList;
1664 m_serialNumberList = NULL;
1670 void StereoTool::profile() {
1678 if (m_profileDialog) {
1679 delete m_profileDialog;
1680 m_profileDialog = NULL;
1686 QPointF leftStart( (*m_startPoint)[Left]->GetSample(),
1687 (*m_startPoint)[Left]->GetLine() );
1688 QPointF leftEnd( (*m_endPoint)[Left]->GetSample(),
1689 (*m_endPoint)[Left]->GetLine() );
1691 QPointF rightStart( (*m_startPoint)[Right]->GetSample(),
1692 (*m_startPoint)[Right]->GetLine() );
1693 QPointF rightEnd( (*m_endPoint)[Right]->GetSample(),
1694 (*m_endPoint)[Right]->GetLine() );
1697 QList< QList<QPoint> > rubberBandVertices;
1698 QList<QPoint> rubberBand1;
1700 m_linkedViewports.at(0)->cubeToViewport( (*m_startPoint)[Left]->GetSample(),
1701 (*m_startPoint)[Left]->GetLine(), sx, sy);
1702 m_linkedViewports.at(0)->cubeToViewport( (*m_endPoint)[Left]->GetSample(),
1703 (*m_endPoint)[Left]->GetLine(), ex, ey);
1704 rubberBand1.push_back( QPoint(sx, sy) );
1705 rubberBand1.push_back( QPoint(ex, ey) );
1707 rubberBandVertices.push_back(rubberBand1);
1709 QList<QPoint> rubberBand2;
1710 m_linkedViewports.at(1)->cubeToViewport( (*m_startPoint)[Right]->GetSample(),
1711 (*m_startPoint)[Right]->GetLine(), sx, sy);
1712 m_linkedViewports.at(1)->cubeToViewport( (*m_endPoint)[Right]->GetSample(),
1713 (*m_endPoint)[Right]->GetLine(), ex, ey);
1714 rubberBand2.push_back( QPoint(sx, sy) );
1715 rubberBand2.push_back( QPoint(ex, ey) );
1717 rubberBandVertices.push_back(rubberBand2);
1720 QLineF leftProfile(leftStart,leftEnd);
1721 QLineF rightProfile(rightStart,rightEnd);
1725 QLineF longProfile, shortProfile;
1726 Cube *longCube, *shortCube;
1727 if ( leftProfile.length() > rightProfile.length() ) {
1728 longProfile = leftProfile;
1729 longCube = m_leftCube;
1730 shortProfile = rightProfile;
1731 shortCube = m_rightCube;
1734 longProfile = rightProfile;
1735 longCube = m_rightCube;
1736 shortProfile = leftProfile;
1737 shortCube = m_leftCube;
1740 QVector<QPointF> profileData;
1741 double elevation = 0.;
1742 double elevationError = 0.;
1744 Pvl regDef = m_pointEditor->templateFileName();
1747 int failureCount = 0;
1748 QApplication::setOverrideCursor(Qt::WaitCursor);
1750 for (
int i = 0; i <= (int) shortProfile.length(); i++) {
1751 double shortSamp=0, shortLine=0, longSamp=0, longLine=0;
1753 shortSamp = shortProfile.pointAt( 1/shortProfile.length() * i ).x();
1754 shortLine = shortProfile.pointAt( 1/shortProfile.length() * i ).y();
1756 longSamp = longProfile.pointAt( 1/shortProfile.length() * i ).x();
1757 longLine = longProfile.pointAt( 1/shortProfile.length() * i ).y();
1760 ar->PatternChip()->TackCube(shortSamp, shortLine);
1761 ar->PatternChip()->Load(*shortCube);
1762 ar->SearchChip()->TackCube(longSamp, longLine);
1763 ar->SearchChip()->Load( *longCube, *( ar->PatternChip() ), *shortCube );
1766 if ( ar->Success() ) {
1767 longSamp = ar->CubeSample();
1768 longLine = ar->CubeLine();
1773 if ( m_radiusBox->currentText() ==
"DEM Radius" ) {
1774 shortCube->camera()->IgnoreElevationModel(
false);
1775 shortCube->camera()->SetImage(shortSamp, shortLine);
1776 m_baseRadius = shortCube->camera()->LocalRadius(
1777 shortCube->camera()->GetLatitude(),
1778 shortCube->camera()->GetLongitude() );
1779 if ( !m_baseRadius.
isValid() ) {
1780 QString message =
"Invalid Dem radius, defaulting to ellipsoidal.";
1781 QMessageBox::warning(m_stereoTool,
"Invalid Dem radius", message);
1782 m_baseRadius = m_targetRadius;
1786 shortCube->camera()->IgnoreElevationModel(
true);
1787 longCube->camera()->IgnoreElevationModel(
true);
1789 shortCube->camera()->SetImage(shortSamp, shortLine);
1790 longCube->camera()->SetImage(longSamp,longLine);
1791 double radius, lat, lon, sepang;
1792 if (Stereo::elevation( *shortCube->camera(), *longCube->camera(),
1793 radius, lat, lon, sepang, elevationError) )
1794 elevation = radius - m_baseRadius.
meters();
1795 profileData.append( QPointF(i, elevation) );
1804 QString message =
"Error registering cubes along profile line.\n";
1805 message +=
"Image 1 Sample = " + QString::number(shortSamp);
1806 message +=
" Line = " + QString::number(shortLine);
1807 message +=
"\nImage 2 Sample = " + QString::number(longSamp);
1808 message +=
" Line = " + QString::number(longLine) +
"\n\n";
1809 message += e.toString();
1810 QMessageBox::critical(m_stereoTool,
"Error", message);
1811 rubberBandTool()->
clear();
1815 QApplication::restoreOverrideCursor();
1818 QString message =
"Registration attempts (pixels on line) = " +
1819 QString::number( (
int)shortProfile.length() ) +
1820 "\n\nRegistration failures = " +
1821 QString::number(failureCount) +
1822 "\n\nYou can adjust registration parameters in the "
1823 "\"Options\" menu in the Elevation Calculator window. "
1824 "Select \"Options\", then \"Registration\", then either "
1825 "\"Select registration template\" or "
1826 "\"View/edit registration template\".";
1827 QMessageBox::information(m_stereoTool,
"Registration Report", message);
1829 if ( ( (
int)shortProfile.length() + 1 - failureCount ) < 2 ) {
1830 QString message =
"Cannot create profile, all auto-registration between ";
1831 message +=
"the left and right cubes along the profile failed. Try ";
1832 message +=
"adjusting the registration parameters.";
1833 QMessageBox::critical(m_stereoTool,
"Error", message);
1837 plotWindow->setAxisLabel(0,
"Elevation (meters)");
1841 plotCurve->setData(
new QwtPointSeriesData(profileData) );
1842 plotCurve->setTitle(
"Elevations (Meters)");
1843 plotCurve->setPen( QPen(Qt::white) );
1844 plotCurve->setColor(Qt::white);
1851 plotCurve->setSource(m_linkedViewports, rubberBandVertices, bands);
1852 plotWindow->add(plotCurve);
1854 delete m_profileDialog;
1855 m_profileDialog = NULL;
1864 void StereoTool::updateLabels() {
1866 QString elevationLabel, elevationErrorLabel;
1867 QString baseRadiiLabel, leftDemRadiiLabel, rightDemRadiiLabel;
1869 elevationLabel =
"Elevation: " +
1870 QString::number( m_editPoint->
GetMeasure(Left)->
1871 GetFocalPlaneMeasuredX(),
'f', 6 );
1872 elevationErrorLabel =
"Elevation Error: " +
1873 QString::number( m_editPoint->
GetMeasure(Left)->
1874 GetFocalPlaneMeasuredY(),
'f', 6 );
1875 baseRadiiLabel =
"Local Radii: " + QString::number(
1876 m_baseRadius.
meters(),
'f', 6 );
1879 leftCamera->
SetImage( (*m_editPoint)[Left]->GetSample(),
1880 (*m_editPoint)[Left]->GetLine() );
1881 double leftDemRadii =
1882 leftCamera->GetSurfacePoint().GetLocalRadius().meters();
1883 leftDemRadiiLabel =
"Left DEM Radii: " +
1884 QString::number(leftDemRadii,
'f', 6);
1887 rightCamera->
SetImage( (*m_editPoint)[Right]->GetSample(),
1888 (*m_editPoint)[Right]->GetLine() );
1889 double rightDemRadii =
1890 rightCamera->GetSurfacePoint().GetLocalRadius().meters();
1891 rightDemRadiiLabel =
"Right DEM Radii: " +
1892 QString::number(rightDemRadii,
'f', 6);
1895 elevationLabel =
"Elevation: ";
1896 elevationErrorLabel =
"Elevation Error: ";
1897 baseRadiiLabel =
"Local Radii: ";
1898 leftDemRadiiLabel =
"Left DEM Radii: ";
1899 rightDemRadiiLabel =
"Right DEM Radii: ";
1901 m_elevationLabel->setText(elevationLabel);
1902 m_elevationErrorLabel->setText(elevationErrorLabel);
1903 m_baseRadiiLabel->setText(baseRadiiLabel);
1904 m_leftDemRadiiLabel->setText(leftDemRadiiLabel);
1905 m_rightDemRadiiLabel->setText(rightDemRadiiLabel);
1910 void StereoTool::readSettings() {
1911 FileName config(
"$HOME/.Isis/qview/Stereo Tool.config");
1912 QSettings settings(config.expanded(),
1913 QSettings::NativeFormat);
1914 m_showWarning = settings.value(
"showWarning",
true).toBool();
1920 void StereoTool::writeSettings() {
1921 FileName config(
"$HOME/.Isis/qview/Stereo Tool.config");
1922 QSettings settings(config.expanded(),
1923 QSettings::NativeFormat);
1924 settings.setValue(
"showWarning", m_showWarning);
@ 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.
static AutoReg * Create(Pvl &pvl)
Create an AutoReg object using a PVL specification.
virtual bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
@ Manual
Hand Measured (e.g., qnet)
bool setTemplateFile(QString)
Allows user to choose a new template file by opening a window from which to select a filename.
void setRightMeasure(ControlMeasure *rightMeasure, Cube *rightCube, QString pointId)
Set the measure displayed in the right ChipViewport.
void setLeftMeasure(ControlMeasure *leftMeasure, Cube *leftCube, QString pointId)
Set the measure displayed in the left ChipViewport.
Status SetAprioriSurfacePoint(SurfacePoint aprioriSP)
This updates the apriori surface point.
void Add(ControlMeasure *measure)
Add a measurement to the control point, taking ownership of the measure in the process.
@ 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.
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube's serial number.
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.
Camera * camera()
Return a camera associated with the cube.
virtual QString fileName() const
Returns the opened cube's filename.
This is a plot curve with information relating it to a particular cube or region of a cube.
Widget to display Isis cubes for qt apps.
Distance measurement, usually in meters.
bool isValid() const
Test if this distance has been initialized or not.
@ Meters
The distance is being specified in meters.
double meters() const
Get the distance in meters.
File name manipulation and expansion.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Adds specific functionality to C++ strings.
This class is designed to encapsulate the concept of a Latitude.
This class is designed to encapsulate the concept of a Longitude.
Cube display widget for certain Isis MDI applications.
@ Elevation
The data is an elevation (in meters).
@ PixelNumber
The data is a pixel #.
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.
void IgnoreElevationModel(bool ignore)
This allows you to ignore the cube elevation model and use the ellipse.
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
Serial Number list generator.
bool hasSerialNumber(QString sn)
Determines whether or not the requested serial number exists in 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.
virtual Target * target() const
Returns a pointer to the target object.
This class defines a body-fixed surface point.
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
double Sample() const
Returns the current line value of the camera model or projection.
double UniversalLongitude() const
Returns the universal longitude of the camera model or projection.
bool SetImage(double sample, double line)
Returns whether the sample/line postion was set successfully in the camera model or projection.
double UniversalLatitude() const
Returns the universal latitude 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.
bool SetGround(Latitude lat, Longitude 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.
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.