1 #include "StereoTool.h" 10 #include <QFileDialog> 11 #include <QInputDialog> 13 #include <QMessageBox> 14 #include <QStackedWidget> 16 #include "AbstractPlotTool.h" 24 #include "ControlPointEdit.h" 34 #include "MainWindow.h" 38 #include "ProfileDialog.h" 39 #include "PvlEditDialog.h" 43 #include "RubberBandTool.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.";
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" ) {
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 " +
827 QMessageBox::critical(m_stereoTool,
"Error", message);
834 QString message =
"Cannot initialize universal ground map for" +
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',
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() {
904 QMessageBox::critical(m_stereoTool,
"Error setting stereo pair", message);
905 rubberBandTool()->
clear();
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() ) {
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.";
946 QMessageBox::critical(m_stereoTool,
"Error", message);
951 else if ( rubberBandTool()->mouseButton() & Qt::MidButton ) {
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";
989 QMessageBox::critical(m_stereoTool,
"Error", message);
991 rubberBandTool()->
clear();
1001 if ( rubberBandTool()->mouseButton() & Qt::RightButton ) {
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";
1015 QMessageBox::critical(m_stereoTool,
"Error", message);
1016 m_startPoint = NULL;
1017 rubberBandTool()->
clear();
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";
1036 QMessageBox::critical(m_stereoTool,
"Error", message);
1037 m_startPoint = NULL;
1039 rubberBandTool()->
clear();
1046 m_profileDialog =
new ProfileDialog();
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() {
1083 rubberBandTool()->vertices()[0].ry(),
1085 if ( cvp->
cube() == m_leftCube ) {
1099 QString message =
"Cannot create control point.\n\n";
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() {
1120 rubberBandTool()->vertices()[1].ry(),
1122 if ( cvp->
cube() == m_leftCube ) {
1136 QString message =
"Cannot create control point.\n\n";
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);
1260 newPoint->
Add(mLeft);
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) {
1356 m_startPoint->
GetMeasure(serialNumber)->GetLine(),
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;
1396 m_controlNet->GetMeasuresInCube(serialNumber);
1398 for (
int i = 0; i < measures.count(); i++) {
1401 double samp = m->GetSample();
1402 double line = m->GetLine();
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();
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() );
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;
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();
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();
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 << endl;
1634 for (
int i = 0; i < m_controlNet->GetNumPoints(); i++) {
1637 data = p.
GetId() +
"," +
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 << 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() );
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);
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;
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();
1773 if ( m_radiusBox->currentText() ==
"DEM Radius" ) {
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;
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";
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);
1841 plotCurve->
setData(
new QwtPointSeriesData(profileData) );
1842 plotCurve->setTitle(
"Elevations (Meters)");
1843 plotCurve->
setPen( QPen(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 =
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);
This class defines a body-fixed surface point.
Status SetType(MeasureType type)
Set how the coordinate was obtained.
Cube display widget for certain Isis MDI applications.
bool HasSerialNumber(QString serialNumber) const
Return true if given serial number exists in point.
double meters() const
Get the distance in meters.
void IgnoreElevationModel(bool ignore)
This allows you to ignore the cube elevation model and use the ellipse.
double Line() const
Returns the current line value of the camera model or projection.
const double Null
Value for an Isis Null pixel.
void Add(ControlMeasure *measure)
Add a measurement to the control point, taking ownership of the measure in the process.
bool hasSerialNumber(QString sn)
Determines whether or not the requested serial number exists in the list.
File name manipulation and expansion.
Camera * camera()
Return a camera associated with the cube.
void setSource(CubeViewport *cvp, QList< QPoint > screenPoints, int band=-1)
Tell this plot curve from where its data originated.
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube's serial number.
QString serialNumber(const QString &filename)
Return a serial number given a filename.
Namespace for the standard library.
void TackCube(const double cubeSample, const double cubeLine)
This sets which cube position will be located at the chip tack position.
This class is designed to encapsulate the concept of a Latitude.
AutoReg::RegisterStatus Register()
Walk the pattern chip through the search chip to find the best registration.
Chip * SearchChip()
Return pointer to search chip.
Widget to display Isis cubes for qt apps.
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Distance measurement, usually in meters.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
double degrees() const
Get the angle in units of Degrees.
A Free point is a Control Point that identifies common measurements between two or more cubes...
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
Status SetDiameter(double diameter)
Set the crater diameter at the coordinate.
double CubeSample() const
Return the search chip cube sample that best matched.
Distance LocalRadius() const
Returns the local radius at the intersection point.
void setRightMeasure(ControlMeasure *rightMeasure, Cube *rightCube, QString pointId)
Set the measure displayed in the right ChipViewport.
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
This class is designed to encapsulate the concept of a Longitude.
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
bool setTemplateFile(QString)
Allows user to choose a new template file by opening a window from which to select a filename...
Hand Measured (e.g., qnet)
QString GetId() const
Return the Id of the control point.
Target * target() const
Returns a pointer to the target object.
bool SetGround(Latitude lat, Longitude lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
Contains multiple PvlContainers.
Chip * PatternChip()
Return pointer to pattern chip.
This is a plot curve with information relating it to a particular cube or region of a cube...
#define _FILEINFO_
Macro for the filename and line number.
A type of error that could only have occurred due to a mistake on the user's part (e...
Status SetAprioriSurfacePoint(SurfacePoint aprioriSP)
This updates the apriori surface point.
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
double UniversalLatitude() const
Returns the universal latitude of the camera model or projection.
double CubeLine() const
Return the search chip cube line that best matched.
bool isValid() const
Test if this distance has been initialized or not.
ShapeModel * shape() const
Return the shape.
Longitude GetLongitude() const
Returns a positive east, 0-360 domain longitude object at the surface intersection point in the body ...
void setColor(const QColor &color)
Set the color of this curve and it's markers.
bool Success() const
Return whether the match algorithm succeeded or not.
void setAxisLabel(int axisId, QString title)
Sets the plots given axis title to the given string.
Container for cube-like labels.
void Load(Cube &cube, const double rotation=0.0, const double scale=1.0, const int band=1)
Load cube data into the Chip.
Status SetType(PointType newType)
Updates the control point's type.
bool SetImage(double sample, double line)
Returns whether the sample/line postion was set successfully in the camera model or projection...
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
static AutoReg * Create(Pvl &pvl)
Create an AutoReg object using a PVL specification.
void setData(QwtSeriesData< QPointF > *data)
This method sets the data for the curve, then sets the value for the markers associated with the curv...
QString name() const
Gets the shape name.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Status SetFocalPlaneMeasured(double x, double y)
Set the focal plane x/y for the measured line/sample.
QString toString() const
Returns a string representation of this exception.
The data is an elevation (in meters).
virtual QString fileName() const
Returns the opened cube's filename.
static QString UserName()
Returns the user name.
SurfacePoint GetSurfacePoint() const
Returns the surface point (most efficient accessor).
Adds specific functionality to C++ strings.
Status SetChooserName()
Set chooser name to a user who last changed the coordinate.
Namespace for ISIS/Bullet specific routines.
bool SetUniversalGround(double lat, double lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
PvlEditDialog creates a QDialog window in which a QTextEdit box displays the contents of a pvl file...
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
Status SetCoordinate(double sample, double line)
Set the coordinate of the measurement.
The distance is being specified in meters.
Status SetDateTime()
Date Time - Creation Time.
double Sample() const
Returns the current line value of the camera model or projection.
void setPen(const QPen &pen)
Sets the plot pen to the passed-in pen.
PointType GetType() const
Serial Number list generator.
virtual void add(CubePlotCurve *pc)
This method adds the curves to the plot.
Distance GetLocalRadius() const
Return the radius of the surface point.
double UniversalLongitude() const
Returns the universal longitude of the camera model or projection.
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
Latitude GetLatitude() const
Returns a planetocentric latitude object at the surface intersection point in body fixed...
double GetDiameter() const
Return the diameter of the crater in pixels (0 implies no crater)
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void setLeftMeasure(ControlMeasure *leftMeasure, Cube *leftCube, QString pointId)
Set the measure displayed in the left ChipViewport.
IO Handler for Isis Cubes.