Isis 3 Programmer Reference
StereoTool.cpp
1#include "StereoTool.h"
2
3#include <iomanip>
4#include <cmath>
5#include <vector>
6
7#include <QAction>
8#include <QCheckBox>
9#include <QComboBox>
10#include <QFileDialog>
11#include <QInputDialog>
12#include <QMenuBar>
13#include <QMessageBox>
14#include <QStackedWidget>
15
16#include "AbstractPlotTool.h"
17#include "Application.h"
18#include "AutoReg.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"
26#include "Distance.h"
27#include "FileName.h"
28#include "History.h"
29#include "IException.h"
30#include "IString.h"
31#include "iTime.h"
32#include "Latitude.h"
33#include "Longitude.h"
34#include "MainWindow.h"
35#include "MdiCubeViewport.h"
36#include "PlotCurve.h"
37#include "PlotWindow.h"
38#include "ProfileDialog.h"
39#include "PvlEditDialog.h"
40#include "PvlObject.h"
41#include "Projection.h"
42#include "QIsisApplication.h"
43#include "RubberBandTool.h"
44#include "SerialNumber.h"
45#include "Stereo.h"
46#include "SurfacePoint.h"
47#include "Target.h"
48#include "ToolPad.h"
49#include "UniversalGroundMap.h"
50
51
52using namespace std;
53
54
55namespace Isis {
56 // initialize static
57/* !!!! TODOS !!!!
58
591. If DEM radius comboBox, update to DEM , when?
60
61
62*/
63
64
65
66 QString StereoTool::lastPtIdValue = "";
67
75
76 m_editPoint = NULL;
77 m_startPoint = NULL;
78 m_endPoint = NULL;
79
80 m_serialNumberList = NULL;
81 m_controlNet = NULL;
82 m_leftCube = NULL;
83 m_rightCube = NULL;
84 m_leftGM = NULL;
85 m_rightGM = NULL;
86
87 m_profileDialog = NULL;
88
89 m_showWarning = true;
90
91 m_targetRadius = Distance(0., Distance::Meters);
92 m_baseRadius = Distance(0., Distance::Meters);
93
94 createStereoTool(parent);
95 connect( this, SIGNAL( toolActivated() ), this, SLOT( activateTool() ) );
96 }
97
98
104
105 m_stereoTool = new QMainWindow(parent);
106 m_stereoTool->setWindowTitle("Elevation Calculator (via stereo pairs)");
107
108 createMenus();
109
110 // Place everything in a grid
111 QGridLayout *gridLayout = new QGridLayout();
112 //gridLayout->setSizeConstraint(QLayout::SetFixedSize);
113 // ??? Very tacky-hardcoded to ChipViewport size of ControlPointEdit + xtra.
114 // Is there a better way to do this?
115 gridLayout->setColumnMinimumWidth(0, 310);
116 gridLayout->setColumnMinimumWidth(1, 310);
117 // grid row
118 int row = 0;
119
120 m_ptIdValue = new QLabel();
121 gridLayout->addWidget(m_ptIdValue, row++, 0);
122
123 m_leftCubeLabel = new QLabel();
124 m_rightCubeLabel = new QLabel();
125 gridLayout->addWidget(m_leftCubeLabel, row, 0);
126 gridLayout->addWidget(m_rightCubeLabel, row++, 1);
127
128 m_pointEditor = new ControlPointEdit(NULL, parent, true);
129 gridLayout->addWidget(m_pointEditor, row++, 0, 1, 3);
130 connect( m_pointEditor, SIGNAL( measureSaved() ), this, SLOT( measureSaved() ) );
131 m_pointEditor->show();
132 connect(this,
133 SIGNAL( stretchChipViewport(Stretch *, CubeViewport *) ),
134 m_pointEditor,
135 SIGNAL( stretchChipViewport(Stretch *, CubeViewport *) ) );
136
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);
146
147 m_baseRadiiLabel = new QLabel;
148 m_baseRadiiLabel->setToolTip("Subtracted from the calculated radius to "
149 "determine elevation.");
150// m_baseRadiiLabel->setToolTip("Local Radius");
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);
158
159// QPushButton *elevationButton = new QPushButton("Calculate Elevation");
160// connect(elevationButton, SIGNAL(clicked() ),
161// this, SLOT(calculateElevation() ));
162// gridLayout->addWidget(elevationButton, row++, 1);
163
164 QWidget *cw = new QWidget();
165 cw->setLayout(gridLayout);
166 m_stereoTool->setCentralWidget(cw);
167
168 connect( this, SIGNAL( editPointChanged() ), this, SLOT( paintAllViewports() ) );
169
170 }
171
172
179
180 m_save = new QAction(m_stereoTool);
181 m_save->setText("Save Elevation Data...");
182 QString whatsThis =
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);
187
188 QAction *saveAs = new QAction(m_stereoTool);
189 saveAs->setText("Save Elevation Data As...");
190 whatsThis =
191 "<b>Function:</b> Saves the elevation calulations to a file.";
192 saveAs->setWhatsThis(whatsThis);
193 connect( saveAs, SIGNAL( triggered() ), this, SLOT( saveAsElevations() ) );
194
195 QAction *closeStereoTool = new QAction(m_stereoTool);
196 closeStereoTool->setText("&Close");
197 closeStereoTool->setShortcut(Qt::ALT + Qt::Key_F4);
198 whatsThis =
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() ) );
203
204 QMenu *fileMenu = m_stereoTool->menuBar()->addMenu("&File");
205 fileMenu->addAction(m_save);
206 fileMenu->addAction(saveAs);
207 fileMenu->addAction(closeStereoTool);
208
209 QAction *templateFile = new QAction(m_stereoTool);
210 templateFile->setText("&Set registration template");
211 whatsThis =
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() ) );
215
216 QAction *viewTemplate = new QAction(m_stereoTool);
217 viewTemplate->setText("&View/edit registration template");
218 whatsThis =
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() ) );
223
224
225 QMenu *optionMenu = m_stereoTool->menuBar()->addMenu("&Options");
226 QMenu *regMenu = optionMenu->addMenu("&Registration");
227
228 regMenu->addAction(templateFile);
229 regMenu->addAction(viewTemplate);
230 // registrationMenu->addAction(interestOp);
231
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() ));
235
236 QMenu *helpMenu = m_stereoTool->menuBar()->addMenu("&Help");
237 helpMenu->addAction(showHelpAct);
238
239 }
240
241
242
251 QAction *action = new QAction(pad);
252 action->setIcon( QPixmap(toolIconDir() + "/3d-glasses-icon.png") );
253 action->setToolTip("Stereo");
254 action->setWhatsThis("<strong>Functionality:</strong> "
255 "<ul>"
256 "<li>Calculate elevation at a single point by creating a "
257 "control point between the image pair. "
258 "<ul>"
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>");
268 return action;
269 }
270
271
272
280 QWidget *StereoTool::createToolBarWidget(QStackedWidget *parent) {
281 QWidget *hbox = new QWidget(parent);
282
283 QLabel *boxLabel = new QLabel("Local Radius:");
284 m_radiusBox = new QComboBox(hbox);
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");
289 QString text =
290 "<b>Function: </b>Source for the local radius used for elevation "
291 "calculations.";
292 m_radiusBox->setWhatsThis(text);
293 connect( m_radiusBox, SIGNAL( activated(int) ),
294 this, SLOT( updateRadiusLineEdit() ));
295
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\"");
303 text =
304 "<b>Function: </b>Custom local radius used to calculate elevations. "
305 "This can be changed by selecting \"Custom Radius\" in the box to "
306 "the left.";
307 m_radiusLineEdit->setWhatsThis(text);
308// connect(m_radiusLineEdit, SIGNAL(textEdited(QString) ),
309// this, SLOT(userBaseRadius(QString) ));
310 connect( m_radiusLineEdit, SIGNAL( editingFinished() ),
311 this, SLOT( userBaseRadius() ));
312 // Do not enable unless radius box set to Custom Radius
313 m_radiusLineEdit->setEnabled(false);
314
315 QLabel *radiusUnit = new QLabel("Meters");
316
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() ));
322
323 QHBoxLayout *layout = new QHBoxLayout;
324 layout->setMargin(0);
325 layout->addWidget(AbstractPlotTool::createToolBarWidget(parent) );
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);
333
334 readSettings();
335
336 return hbox;
337 }
338
339
340
341 void StereoTool::activateTool() {
342
343 warningDialog();
344 }
345
346
347
349 return new PlotWindow("Elevation Profile", PlotCurve::PixelNumber,
351 qobject_cast<QWidget *>( parent() ) );
352
353 }
354
355
356
359
360
361
362 void StereoTool::warningDialog() {
363
364 if (m_showWarning) {
365 QDialog *warningDialog = new QDialog(m_stereoTool);
366
367 QVBoxLayout *mainLayout = new QVBoxLayout;
368 warningDialog->setLayout(mainLayout);
369
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);
380
381 QPushButton *okButton = new QPushButton("OK");
382 mainLayout->addStretch();
383 mainLayout->addWidget(okButton);
384 connect( okButton, SIGNAL( clicked() ), warningDialog, SLOT( accept() ));
385
386 if ( warningDialog->exec() ) {
387 if ( showWarning->isChecked() ) m_showWarning = false;
388 }
389 writeSettings();
390 }
391
392 }
393
394
395
396 void StereoTool::showHelp() {
397
398 QDialog *helpDialog = new QDialog(m_stereoTool);
399 helpDialog->setWindowTitle("Stereo Tool Help");
400
401 QVBoxLayout *mainLayout = new QVBoxLayout;
402 helpDialog->setLayout(mainLayout);
403
404 QLabel *stereoTitle = new QLabel("<h2>Stereo Tool</h2>");
405 mainLayout->addWidget(stereoTitle);
406
407 QLabel *stereoSubtitle = new QLabel("A tool for calculating point elevations "
408 "and elevation profiles using stereo pairs "
409 "of cubes.");
410 stereoSubtitle->setWordWrap(true);
411 mainLayout->addWidget(stereoSubtitle);
412
413 QTabWidget *tabArea = new QTabWidget;
414 tabArea->setDocumentMode(true);
415 mainLayout->addWidget(tabArea);
416
417 // TAB 1 - Overview
418 QScrollArea *overviewTab = new QScrollArea;
419 overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
420 overviewTab->setWidgetResizable(true);
421 QWidget *overviewContainer = new QWidget;
422 QVBoxLayout *overviewLayout = new QVBoxLayout;
423 overviewContainer->setLayout(overviewLayout);
424
425 QLabel *purposeTitle = new QLabel("<h2>Purpose</h2>");
426 overviewLayout->addWidget(purposeTitle);
427
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);
437
438 QLabel *warningsTitle = new QLabel("<h2>Warnings</h2>");
439 overviewLayout->addWidget(warningsTitle);
440
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);
447
448 overviewTab->setWidget(overviewContainer);
449
450 // TAB 2 - Quick Start
451 QScrollArea *quickTab = new QScrollArea;
452 quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
453 quickTab->setWidgetResizable(true);
454 QWidget *quickContainer = new QWidget;
455 QVBoxLayout *quickLayout = new QVBoxLayout;
456 quickContainer->setLayout(quickLayout);
457
458 QLabel *quickTitle = new QLabel("<h2>Quick Start</h2>");
459 quickLayout->addWidget(quickTitle);
460
461 QLabel *quickSubTitle = new QLabel("<h3>Preparation:</h3>");
462 quickLayout->addWidget(quickSubTitle);
463
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);
469
470 QLabel *quickFunctionTitle = new QLabel("<h3>Cube Viewport Functions:</h3>");
471 quickLayout->addWidget(quickFunctionTitle);
472
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);
479
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);
501
502 quickTab->setWidget(quickContainer);
503
504 // TAB 3 - Control Point Editing
505 QScrollArea *controlPointTab = new QScrollArea;
506 controlPointTab->setWidgetResizable(true);
507 controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
508 QWidget *controlPointContainer = new QWidget;
509 QVBoxLayout *controlPointLayout = new QVBoxLayout;
510 controlPointContainer->setLayout(controlPointLayout);
511
512 QLabel *controlPointTitle = new QLabel("<h2>Control Point Editing</h2>");
513 controlPointLayout->addWidget(controlPointTitle);
514
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);
521
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);
533
534 QLabel *controlPointEditing = new QLabel(
535 "<h4>Changing Measure Locations</h4>"
536 "<p>The measure location can be adjusted by:"
537 "<ul>"
538 "<li>Move the cursor location under the crosshair by clicking the left mouse "
539 "button</li>"
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>"
542 "</ul></p>"
543 "<h4>Other Point Editor Functions</h4>"
544 "<p>Along the right border of the window:</p>"
545 "<ul>"
546 "<li><strong>Geom:</strong> Geometrically match the right view to the left"
547 "view</li>"
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"
553 "view</li>"
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"
561 "blinking.</li>"
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);
571
572 controlPointTab->setWidget(controlPointContainer);
573
574
575
576 tabArea->addTab(overviewTab, "&Overview");
577 tabArea->addTab(quickTab, "&Quick Start");
578 tabArea->addTab(controlPointTab, "&Control Point Editing");
579
580 QHBoxLayout *buttonsLayout = new QHBoxLayout;
581 // Flush the buttons to the right
582 buttonsLayout->addStretch();
583
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);
590
591 mainLayout->addLayout(buttonsLayout);
592
593 helpDialog->show();
594
595
596 }
597
598
599
600 void StereoTool::userBaseRadius() {
601 // TODO test validity
602 try {
603 m_baseRadius = Distance(m_radiusLineEdit->text().toDouble(),
605
606 // If stereo Tool visible and has valid point, update elevation and
607 // save new elevation to point
608 if (m_stereoTool->isVisible() && m_editPoint != NULL) {
609 calculateElevation();
610 }
611 }
612 catch (IException &e) {
613 QString message = "Invalid base radius entered.";
614 message += e.toString();
615 m_radiusLineEdit->setText("");
616 QMessageBox::critical(m_stereoTool, "Error", message);
617 m_baseRadius = Distance(0., Distance::Meters);
618 return;
619 }
620
621 }
622
623
624
625 void StereoTool::updateRadiusLineEdit() {
626
627
628 if ( m_radiusBox->currentText() == "Ellipsoid Equitorial Radius" ) {
629 if ( m_targetRadius.isValid() ) {
630 m_radiusLineEdit->setText( QString::number( m_targetRadius.meters(), 'f',
631 6) );
632 m_baseRadius = m_targetRadius;
633 }
634 else {
635 m_radiusLineEdit->setText("");
636 }
637 m_radiusLineEdit->setReadOnly(true);
638 m_radiusLineEdit->setEnabled(false);
639 }
640 else if ( m_radiusBox->currentText() == "DEM Radius" ) {
641 // If cubes set, make sure they have an elevation model
642 if (m_leftCube) {
643 m_leftCube->camera()->IgnoreElevationModel(false);
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);
649
650 m_radiusLineEdit->setReadOnly(true);
651 m_radiusLineEdit->setEnabled(false);
652 return;
653 }
654 }
655 m_radiusLineEdit->setText("");
656 m_radiusLineEdit->setReadOnly(true);
657 m_radiusLineEdit->setEnabled(false);
658 m_baseRadius = Distance(0., Distance::Meters);
659 }
660 else { // "Custom Radius"
661 m_radiusLineEdit->setReadOnly(false);
662 m_radiusLineEdit->setEnabled(true);
663 }
664
665 // If stereo Tool visible and has valid point, update elevation
666 if ( m_stereoTool->isVisible() && m_editPoint != NULL ) {
667 calculateElevation();
668 }
669 }
670
671
672
673 void StereoTool::setupFiles() {
674
675 /* TODO
676 .5 Get vector of all linked viewports
677 1. If no files linked or > 2 linked, print errror & return
678 2. Check if new files
679 if yes: clear old
680 if no: return
681
682 */
683 m_linkedViewports.clear();
684 for (int i = 0; i < (int) cubeViewportList()->size(); i++) {
685 if ( (*( cubeViewportList() ) )[i]->isLinked() )
686 m_linkedViewports.push_back( (*( cubeViewportList() ) )[i]);
687 }
688
689 if ( m_linkedViewports.size() < 2 ) {
690 IString message = "Two cube viewports containing a stereo pair "
691 "need to be linked.";
692 throw IException(IException::User, message, _FILEINFO_);
693 }
694 if ( m_linkedViewports.size() > 2 ) {
695 IString message = "Only two cube viewports containing a stereo pair "
696 "may be linked.";
697 throw IException(IException::User, message, _FILEINFO_);
698 }
699
700 // If linked viewports contain the same cubes, simply return,
701 // all data should be retained.
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 ) {
706 return;
707 }
708 }
709
710 // Control net already exists, make sure new cubes are the same target
711 // as the current control net.
712 if (m_controlNet) {
713 if ( m_controlNet->GetTarget() !=
714 m_linkedViewports.at(0)->cube()->camera()->target()->name() ) {
715 // Allow opportunity to save current data before clearing for new
716 // target.
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,
723 QMessageBox::Yes);
724 if (response == QMessageBox::Yes) {
726 }
727 m_stereoTool->setVisible(false);
728 clearNetData();
729 m_controlNet = new ControlNet();
730 m_controlNet->SetTarget(*m_linkedViewports.at(0)->cube()->label());
731 m_serialNumberList = new SerialNumberList(false);
732 }
733 }
734 else {
735 m_controlNet = new ControlNet();
736 m_controlNet->SetTarget(
737 m_linkedViewports.at(0)->cube()->camera()->target()->name() );
738 m_serialNumberList = new SerialNumberList(false);
739 }
740
741
742 // TODO: For now simply clear & set always, but should check if cubes are
743 // not new.
744 clearFiles();
745 setFiles( m_linkedViewports.at(0)->cube(), m_linkedViewports.at(1)->cube() );
746
747 }
748
749
750
761 m_stereoTool->setVisible(false);
762
763 if (m_leftGM) {
764 delete m_leftGM;
765 m_leftGM = NULL;
766 }
767 if (m_rightGM) {
768 delete m_rightGM;
769 m_rightGM = NULL;
770 }
771
772 }
773
774
775
783 void StereoTool::setFiles(Cube *leftCube, Cube *rightCube) {
784
785 // Save off base map cube, but add matchCube to serial number list
786 m_leftCube = leftCube;
787 m_rightCube = rightCube;
788
789 QString leftName = FileName( m_leftCube->fileName() ).name();
790 QString rightName = FileName( m_rightCube->fileName() ).name();
791 // Update cube name labels
792 m_leftCubeLabel->setText(leftName);
793 m_rightCubeLabel->setText(rightName);
794
795 m_leftSN = SerialNumber::Compose(*m_leftCube);
796 m_rightSN = SerialNumber::Compose(*m_rightCube);
797
798 // TODO Do I need list?
799 if ( !m_serialNumberList->hasSerialNumber(m_leftSN) ) {
800 m_serialNumberList->add( m_leftCube->fileName() );
801 }
802 if ( !m_serialNumberList->hasSerialNumber(m_rightSN) ) {
803 m_serialNumberList->add( m_rightCube->fileName() );
804 }
805
806 try {
807 PvlGroup pvlRadii = Target::radiiGroup(m_controlNet->GetTarget());
808 m_targetRadius = Distance(pvlRadii["EquatorialRadius"], Distance::Meters);
809 }
810 catch(IException &e) {
811 QString message = "Could not determine target radius.";
812 QMessageBox::critical(m_stereoTool,"Error",message);
813 m_baseRadius = Distance(0., Distance::Meters);
814 updateRadiusLineEdit();
815 return;
816 }
817 updateRadiusLineEdit();
818
819 // Save off universal ground maps
820 try {
821 m_leftGM = new UniversalGroundMap(*m_leftCube);
822 }
823 catch (IException &e) {
824 QString message = "Cannot initialize universal ground map for " +
825 m_leftCube->fileName() + ".\n";
826 message += e.toString();
827 QMessageBox::critical(m_stereoTool, "Error", message);
828 return;
829 }
830 try {
831 m_rightGM = new UniversalGroundMap(*m_rightCube);
832 }
833 catch (IException &e) {
834 QString message = "Cannot initialize universal ground map for" +
835 m_rightCube->fileName() + ".\n";
836 message += e.toString();
837 QMessageBox::critical(m_stereoTool, "Error", message);
838 return;
839 }
840
841
842 }
843
844
845
851
852 double samp = m_editPoint->GetMeasure(Left)->GetSample();
853 double line = m_editPoint->GetMeasure(Left)->GetLine();
854 m_leftGM->SetImage(samp, line);
855 double lat = m_leftGM->UniversalLatitude();
856 double lon = m_leftGM->UniversalLongitude();
857
858 m_rightGM->SetGround(
860 try {
863 m_targetRadius ) );
864 }
865 catch (IException &e) {
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',
870 6) + "\n";
871 message += e.toString();
872 QMessageBox::critical(m_stereoTool, "Error", message);
873 }
874
875 calculateElevation();
876 emit editPointChanged();
877 }
878
879
880
887 rubberBandTool()->enable(RubberBandTool::LineMode);
888 rubberBandTool()->enablePoints();
889 rubberBandTool()->enableAllClicks();
890 rubberBandTool()->setDrawActiveViewportOnly(true);
891 }
892
893
894
895 void StereoTool::rubberBandComplete() {
896
897// clearProfile();
898
899 try {
900 setupFiles();
901 }
902 catch (IException &e) {
903 QString message = e.toString();
904 QMessageBox::critical(m_stereoTool, "Error setting stereo pair", message);
905 rubberBandTool()->clear();
906 return;
907 }
908
910 if (cvp == NULL)
911 return;
912
913 QString file = cvp->cube()->fileName();
914 QString sn;
915 try {
916 sn = m_serialNumberList->serialNumber(file);
917 }
918 catch (IException &e) {
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);
922 return;
923 }
924
925 if ( rubberBandTool()->figureIsPoint() ) {
926 double samp, line;
927 cvp->viewportToCube( rubberBandTool()->vertices()[0].rx(),
928 rubberBandTool()->vertices()[0].ry(),
929 samp, line );
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);
935 return;
936 }
937 // Find closest control point in network
938 ControlPoint *point;
939 try {
940 point = m_controlNet->FindClosest(sn, samp, line);
941 }
942 catch (IException &e) {
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);
947 return;
948 }
949 modifyPoint(point);
950 }
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);
956 return;
957 }
958
959 // Find closest control point in network
960 ControlPoint *point =
961 m_controlNet->FindClosest(sn, samp, line);
962 // TODO: test for errors and reality
963 if (point == NULL) {
964 QString message = "No points exist for deleting. Create points ";
965 message += "using the right mouse button.";
966 QMessageBox::information(m_stereoTool, "Warning", message);
967 return;
968 }
969 deletePoint(point);
970 }
971 else if ( rubberBandTool()->mouseButton() & Qt::RightButton ) {
972 double lat, lon;
973 if (cvp->cube() == m_leftCube) {
974 m_leftGM->SetImage(samp, line);
975 lat = m_leftGM->UniversalLatitude();
976 lon = m_leftGM->UniversalLongitude();
977 }
978 else {
979 m_rightGM->SetImage(samp, line);
980 lat = m_rightGM->UniversalLatitude();
981 lon = m_rightGM->UniversalLongitude();
982 }
983 try {
984 createPoint(lat, lon);
985 }
986 catch (IException &e) {
987 QString message = "Cannot create control point.\n\n";
988 message += e.toString();
989 QMessageBox::critical(m_stereoTool, "Error", message);
990 m_startPoint = NULL;
991 rubberBandTool()->clear();
992 return;
993 }
994 }
995 }
996 // RubberBand line drawn:
997 else {
998 m_startPoint = NULL;
999 m_endPoint = NULL;
1000 // Right click/drag: Find closest end points
1001 if ( rubberBandTool()->mouseButton() & Qt::RightButton ) {
1002 double samp, line;
1003 cvp->viewportToCube( rubberBandTool()->vertices()[0].rx(),
1004 rubberBandTool()->vertices()[0].ry(),
1005 samp, line );
1006 try {
1007 m_startPoint = m_controlNet->FindClosest(sn, samp, line);
1008 }
1009 catch (IException &e) {
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();
1018 return;
1019 }
1020 cvp->viewportToCube( rubberBandTool()->vertices()[1].rx(),
1021 rubberBandTool()->vertices()[1].ry(),
1022 samp, line );
1023 try {
1024 m_endPoint = m_controlNet->FindClosest(sn, samp, line);
1025 if ( m_startPoint->GetId() == m_endPoint->GetId() ) {
1026 throw IException(IException::User, "No End Point",
1027 _FILEINFO_);
1028 }
1029 }
1030 catch (IException &e) {
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;
1038 m_endPoint = NULL;
1039 rubberBandTool()->clear();
1040 return;
1041 }
1042 profile();
1043 }
1044 else {
1045 // Left click/drag: Create control points at the line endpoints.
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();
1059 }
1060 }
1061 }
1062
1063
1064
1065 void StereoTool::clearProfile() {
1066 m_startPoint = NULL;
1067 m_endPoint = NULL;
1068 rubberBandTool()->clear();
1069 delete m_profileDialog;
1070 m_profileDialog = NULL;
1071 }
1072
1073
1074
1075 void StereoTool::createStartPoint() {
1077 if (cvp == NULL)
1078 return;
1079
1080 double samp, line;
1081 double lat, lon;
1082 cvp->viewportToCube( rubberBandTool()->vertices()[0].rx(),
1083 rubberBandTool()->vertices()[0].ry(),
1084 samp, line );
1085 if ( cvp->cube() == m_leftCube ) {
1086 m_leftGM->SetImage(samp, line);
1087 lat = m_leftGM->UniversalLatitude();
1088 lon = m_leftGM->UniversalLongitude();
1089 }
1090 else {
1091 m_rightGM->SetImage(samp, line);
1092 lat = m_rightGM->UniversalLatitude();
1093 lon = m_rightGM->UniversalLongitude();
1094 }
1095 try {
1096 createPoint(lat, lon);
1097 }
1098 catch (IException &e) {
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();
1105 return;
1106 }
1107 m_startPoint = m_editPoint;
1108 }
1109
1110
1111
1112 void StereoTool::createEndPoint() {
1114 if (cvp == NULL)
1115 return;
1116
1117 double samp, line;
1118 double lat, lon;
1119 cvp->viewportToCube( rubberBandTool()->vertices()[1].rx(),
1120 rubberBandTool()->vertices()[1].ry(),
1121 samp, line );
1122 if ( cvp->cube() == m_leftCube ) {
1123 m_leftGM->SetImage(samp, line);
1124 lat = m_leftGM->UniversalLatitude();
1125 lon = m_leftGM->UniversalLongitude();
1126 }
1127 else {
1128 m_rightGM->SetImage(samp, line);
1129 lat = m_rightGM->UniversalLatitude();
1130 lon = m_rightGM->UniversalLongitude();
1131 }
1132 try {
1133 createPoint(lat, lon);
1134 }
1135 catch (IException &e) {
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();
1143 return;
1144 }
1145 m_endPoint = m_editPoint;
1146
1147 }
1148
1149
1150
1163 void StereoTool::createPoint(double lat, double lon) {
1164
1165 // TODO: ADD AUTOSEED OPTION (CHECKBOX?)
1166
1167 double leftSamp = 0, leftLine = 0;
1168 double rightSamp = 0, rightLine = 0;
1169
1170 // Make sure point exists on both linked cubes
1171 if ( m_leftGM->SetUniversalGround(lat, lon) ) {
1172 leftSamp = m_leftGM->Sample();
1173 leftLine = m_leftGM->Line();
1174
1175 // Make sure point is on Right cube
1176 if ( m_rightGM->SetUniversalGround(lat, lon) ) {
1177 // Make sure point on Right cube
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, " +
1183 m_rightCube->fileName() + ".";
1184 throw IException(IException::User, message, _FILEINFO_);
1185// QString message = "Point does not exist on cube, " +
1186// QString(m_rightCube->fileName().c_str() ) + ".";
1187// QMessageBox::critical(m_stereoTool, "Error", message);
1188// return;
1189 }
1190 }
1191 else {
1192 IString message = "Point does not exist on cube, " +
1193 m_rightCube->fileName() + ".";
1194 throw IException(IException::User, message, _FILEINFO_);
1195// QString message = "Point does not exist on cube, " +
1196// QString(m_rightCube->fileName().c_str() ) + ".";
1197// QMessageBox::critical(m_stereoTool, "Error", message);
1198// return;
1199 }
1200 }
1201 else {
1202 IString message = "Point does not exist on cube, " +
1203 m_leftCube->fileName() + ".";
1204 throw IException(IException::User, message, _FILEINFO_);
1205// QString message = "Point does not exist on cube, " +
1206// QString(m_leftCube->fileName().c_str() ) + ".";
1207// QMessageBox::critical(m_stereoTool, "Error", message);
1208// return;
1209 }
1210
1211 // Point is on both Left and Right cubes, create new control point
1212 ControlPoint *newPoint = NULL;
1213 // Prompt for point Id
1214 bool goodId = false;
1215 while (!goodId) {
1216 bool ok = false;
1217 QString id = QInputDialog::getText(m_stereoTool,
1218 "Point ID", "Enter Point ID:",
1219 QLineEdit::Normal, lastPtIdValue,
1220 &ok);
1221 if (!ok)
1222 // user clicked "Cancel"
1223 {
1224 return;
1225 }
1226 if ( ok && id.isEmpty() ) {
1227 // user clicked "Ok" but did not enter a point ID
1228 QString message = "You must enter a point Id.";
1229 QMessageBox::warning(m_stereoTool, "Warning", message);
1230 }
1231 else {
1232 // Make sure Id doesn't already exist
1233 newPoint = new ControlPoint(id);
1234 if ( m_controlNet->GetNumPoints() > 0 &&
1235 m_controlNet->ContainsPoint(newPoint->GetId() ) ) {
1236 QString message = "A ControlPoint with Point Id = [" +
1237 newPoint->GetId() +
1238 "] already exists. Re-enter unique Point Id.";
1239 QMessageBox::warning(m_stereoTool, "Unique Point Id", message);
1240 }
1241 else {
1242 goodId = true;
1243 lastPtIdValue = id;
1244 }
1245 }
1246 }
1247
1248 newPoint->SetType(ControlPoint::Free);
1251 m_targetRadius) );
1252
1253 // Set first measure to Left
1254 ControlMeasure *mLeft = new ControlMeasure;
1255 mLeft->SetCubeSerialNumber(m_leftSN);
1256 mLeft->SetCoordinate(leftSamp, leftLine);
1257 mLeft->SetType(ControlMeasure::Manual);
1258 mLeft->SetDateTime();
1259 mLeft->SetChooserName( Application::UserName() );
1260 newPoint->Add(mLeft);
1261 // Second measure is Right measure
1262 ControlMeasure *mRight = new ControlMeasure;
1263 mRight->SetCubeSerialNumber(m_rightSN);
1264 mRight->SetCoordinate(rightSamp, rightLine);
1265 mRight->SetType(ControlMeasure::Manual);
1266 mRight->SetDateTime();
1267 mRight->SetChooserName( Application::UserName() );
1268 newPoint->Add(mRight);
1269
1270 // Add new control point to control network
1271 m_controlNet->AddPoint(newPoint);
1272 // Read newly added point
1273 m_editPoint = m_controlNet->GetPoint( (QString) newPoint->GetId() );
1274 // Load new point in StereoTool
1275 loadPoint();
1276 m_stereoTool->setVisible(true);
1277 m_stereoTool->raise();
1278
1279 emit editPointChanged();
1280 }
1281
1282
1295
1296 m_editPoint = point;
1297 // Change point in viewport to red so user can see what point they are
1298 // about to delete.
1299 emit editPointChanged();
1300
1301 //loadPoint();
1302
1303 m_controlNet->DeletePoint( m_editPoint->GetId() );
1304 m_stereoTool->setVisible(false);
1305 m_editPoint = NULL;
1306
1307 emit editPointChanged();
1308 }
1309
1310
1318
1319 m_editPoint = point;
1320 loadPoint();
1321 m_stereoTool->setVisible(true);
1322 m_stereoTool->raise();
1323 emit editPointChanged();
1324 }
1325
1326
1333
1334 // Initialize pointEditor with measures
1335 m_pointEditor->setLeftMeasure( m_editPoint->GetMeasure(Left), m_leftCube,
1336 m_editPoint->GetId() );
1337 m_pointEditor->setRightMeasure( m_editPoint->GetMeasure(Right),
1338 m_rightCube, m_editPoint->GetId() );
1339
1340 // Write pointId
1341 QString ptId = "Point ID: " + m_editPoint->GetId();
1342 m_ptIdValue->setText(ptId);
1343
1344 updateLabels();
1345 }
1346
1347
1348
1349 void StereoTool::paintProfile(MdiCubeViewport *vp, QPainter *painter,
1350 QString serialNumber) {
1351
1352 // Draw profile
1353 int x1, y1, x2, y2;
1354 //MdiCubeViewport *cvp = cubeViewport();
1355 vp->cubeToViewport( m_startPoint->GetMeasure(serialNumber)->GetSample(),
1356 m_startPoint->GetMeasure(serialNumber)->GetLine(),
1357 x1, y1 );
1358 vp->cubeToViewport( m_endPoint->GetMeasure(serialNumber)->GetSample(),
1359 m_endPoint->GetMeasure(serialNumber)->GetLine(),
1360 x2, y2 );
1361 painter->setPen(Qt::green); // set all other point markers green
1362 painter->drawLine(x1, y1, x2, y2);
1363
1364 }
1365
1366
1367
1375 void StereoTool::paintViewport(MdiCubeViewport *vp, QPainter *painter) {
1376
1378
1379 // Make sure we have points to draw
1380 if ( m_controlNet == NULL || m_controlNet->GetNumPoints() == 0 )
1381 return;
1382
1383 QString serialNumber = SerialNumber::Compose(*vp->cube(), true);
1384
1385 // If viewport serial number not found in control net, return
1386 if ( !m_controlNet->GetCubeSerials().contains(
1387 serialNumber) ) return;
1388
1389 // Draw profile if it exists
1390// if (m_startPoint != NULL && m_endPoint != NULL) {
1391// paintProfile(vp, painter, serialNumber);
1392// }
1393
1394 // Get all measures for this viewport
1395 QList<ControlMeasure *> measures =
1396 m_controlNet->GetMeasuresInCube(serialNumber);
1397 // loop through all measures contained in this cube
1398 for (int i = 0; i < measures.count(); i++) {
1399 ControlMeasure *m = measures[i];
1400 // Find the measurments on the viewport
1401 double samp = m->GetSample();
1402 double line = m->GetLine();
1403 int x, y;
1404 vp->cubeToViewport(samp, line, x, y);
1405 // if the point is ignored,
1406 if ( m->Parent()->IsIgnored() ) {
1407 painter->setPen( QColor(255, 255, 0) ); // set point marker yellow
1408 }
1409 // point is not ignored, but measure matching this image is ignored,
1410 else if ( m->IsIgnored() ) {
1411 painter->setPen( QColor(255, 255, 0) ); // set point marker yellow
1412 }
1413 // Neither point nor measure is not ignored and the measure is fixed,
1414 else if ( m->Parent()->GetType() != ControlPoint::Free) {
1415 painter->setPen(Qt::magenta);// set point marker magenta
1416 }
1417 else {
1418 painter->setPen(Qt::green); // set all other point markers green
1419 }
1420 // draw points
1421 painter->drawLine(x - 5, y, x + 5, y);
1422 painter->drawLine(x, y - 5, x, y + 5);
1423 }
1424
1425 // if StereoTool is open,
1426 if ( m_editPoint != NULL ) {
1427 // and the selected point is in the image,
1428 if ( m_editPoint->HasSerialNumber(serialNumber) ) {
1429 // find the measurement
1430 double samp = (*m_editPoint)[serialNumber]->GetSample();
1431 double line = (*m_editPoint)[serialNumber]->GetLine();
1432 int x, y;
1433 vp->cubeToViewport(samp, line, x, y);
1434 // set point marker red
1435 QBrush brush(Qt::red);
1436 // set point marker bold - line width 2
1437 QPen pen(brush, 2);
1438 // draw the selected point in each image last so it's on top of the rest of the points
1439 painter->setPen(pen);
1440 painter->drawLine(x - 5, y, x + 5, y);
1441 painter->drawLine(x, y - 5, x, y + 5);
1442 }
1443 }
1444
1445 }
1446
1447
1448
1454
1455 // Take care of drawing things on all viewPorts.
1456 // Calling update will cause the Tool class to call all registered tools
1457 // if point has been deleted, this will remove it from the main window
1458 MdiCubeViewport *vp;
1459 for (int i = 0; i < (int) cubeViewportList()->size(); i++) {
1460 vp = (*( cubeViewportList() ) )[i];
1461 vp->viewport()->update();
1462 }
1463 }
1464
1465
1466
1467 void StereoTool::calculateElevation() {
1468 calculateElevation(m_editPoint);
1469 }
1470
1471
1472
1477 void StereoTool::calculateElevation(ControlPoint *point) {
1478
1479 double elevation=0., elevationError=0.;
1480 Camera *leftCamera = m_leftCube->camera();
1481
1482 // If the local radius combo box is set to DEM, get the dem radius
1483 // First, SetImage using the Elevation model, before turning off
1484 // to get camera angles.
1485 if ( m_radiusBox->currentText() == "DEM Radius" ) {
1486 leftCamera->IgnoreElevationModel(false);
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;
1495 }
1496 }
1497
1498 leftCamera->IgnoreElevationModel(true);
1499 leftCamera->SetImage( (*point)[Left]->GetSample(),
1500 (*point)[Left]->GetLine() );
1501 Camera *rightCamera = m_rightCube->camera();
1502 rightCamera->IgnoreElevationModel(true);
1503 rightCamera->SetImage( (*point)[Right]->GetSample(),
1504 (*point)[Right]->GetLine() );
1505
1506 double radius, lat, lon, sepang;
1507 if ( Stereo::elevation( *leftCamera, *rightCamera, radius, lat, lon, sepang,
1508 elevationError ) ) {
1509 elevation = radius - m_baseRadius.meters();
1510// cout<<setprecision(15)<<"radius = "<<radius<<" baseRadius = "<<m_baseRadius.meters()<<" elevation = "<<elevation<<endl;
1511 }
1512 leftCamera->IgnoreElevationModel(false);
1513 rightCamera->IgnoreElevationModel(false);
1514
1515 // Save elevation and error info to the left ControlMeasure FocalPlaneComputeX/Y.
1516 // TODO: Find better way - This is not a good way to do this, using
1517 // ControlMeasure to save other values. Save The baseRadius in Diameter
1518 point->GetMeasure(Left)->SetFocalPlaneMeasured(elevation, elevationError);
1519 point->GetMeasure(Left)->SetDiameter(m_baseRadius.meters() );
1520 updateLabels();
1521
1522 return;
1523 }
1524
1525
1526
1535 QString filename = QFileDialog::getOpenFileName( m_stereoTool,
1536 "Select a registration template", ".",
1537 "Registration template files (*.def *.pvl);;All files (*)" );
1538
1539 if ( filename.isEmpty() )
1540 return;
1541
1542 m_pointEditor->setTemplateFile(filename);
1543 }
1544
1545
1559 try {
1560 // Get the template file from the ControlPointEditor object
1561 Pvl templatePvl( m_pointEditor->templateFileName() );
1562 // Create registration dialog window using PvlEditDialog class
1563 // to view and/or edit the template
1564 PvlEditDialog registrationDialog(templatePvl);
1565 registrationDialog.setWindowTitle( "View or Edit Template File: "
1566 + templatePvl.fileName() );
1567 registrationDialog.resize(550, 360);
1568 registrationDialog.exec();
1569 }
1570 catch (IException &e) {
1571 QString message = e.toString();
1572 QMessageBox::warning(m_stereoTool, "Error", message);
1573 }
1574 }
1575
1576
1583
1584 QString fn = QFileDialog::getSaveFileName( m_stereoTool,
1585 "Choose filename to save under",
1586 ".",
1587 "CSV Files (*.csv)" );
1588 QString filename;
1589
1590 //Make sure the filename is valid
1591 if ( !fn.isEmpty() ) {
1592 if ( !fn.endsWith(".csv") ) {
1593 filename = fn + ".csv";
1594 }
1595 else {
1596 filename = fn;
1597 }
1598 }
1599 //The user cancelled, or the filename is empty
1600 else {
1601 return;
1602 }
1603
1604 m_currentFile.setFileName(filename);
1605
1606 m_save->setEnabled(true);
1607 saveElevations();
1608 }
1609
1610
1611
1612 void StereoTool::saveElevations() {
1613
1614 if ( m_currentFile.fileName().isEmpty() ) return;
1615
1616 bool success = m_currentFile.open(QIODevice::WriteOnly);
1617 if (!success) {
1618 QMessageBox::critical(m_stereoTool, "Error",
1619 "Cannot open file, please check permissions");
1620 m_currentFile.setFileName("");
1621 m_save->setDisabled(true);
1622 return;
1623 }
1624
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;
1630
1631 QString leftFile = FileName( m_leftCube->fileName() ).name();
1632 QString rightFile = FileName( m_rightCube->fileName() ).name();
1633 QString data;
1634 for (int i = 0; i < m_controlNet->GetNumPoints(); i++) {
1635 ControlPoint &p = *( (*m_controlNet)[i] );
1636 SurfacePoint apriori = p.GetAprioriSurfacePoint();
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 ) +
1641 "," +
1642 QString::number( p.GetMeasure(Left)->GetFocalPlaneMeasuredX(), 'f',
1643 6 ) + "," +
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() ) + "," +
1648 rightFile + "," +
1649 QString::number( p.GetMeasure(Right)->GetSample() ) + "," +
1650 QString::number( p.GetMeasure(Right)->GetLine() );
1651 text << data << endl;
1652 }
1653 m_currentFile.close();
1654
1655 }
1656
1657
1658
1659 void StereoTool::clearNetData() {
1660
1661 delete m_controlNet;
1662 m_controlNet = NULL;
1663 delete m_serialNumberList;
1664 m_serialNumberList = NULL;
1665
1666 }
1667
1668
1669
1670 void StereoTool::profile() {
1671
1672// (*m_startPoint)[Left]->SetCoordinate(1361.92,1317.9433);
1673// (*m_endPoint)[Left]->SetCoordinate(1188.43,2763.23);
1674// (*m_startPoint)[Right]->SetCoordinate(867.04,2141.16);
1675// (*m_endPoint)[Right]->SetCoordinate(731.82,2666.75);
1676
1677 // Delete the profile dialog
1678 if (m_profileDialog) {
1679 delete m_profileDialog;
1680 m_profileDialog = NULL;
1681 }
1682
1683// calculateElevation(m_startPoint);
1684// calculateElevation(m_endPoint);
1685
1686 QPointF leftStart( (*m_startPoint)[Left]->GetSample(),
1687 (*m_startPoint)[Left]->GetLine() );
1688 QPointF leftEnd( (*m_endPoint)[Left]->GetSample(),
1689 (*m_endPoint)[Left]->GetLine() );
1690
1691 QPointF rightStart( (*m_startPoint)[Right]->GetSample(),
1692 (*m_startPoint)[Right]->GetLine() );
1693 QPointF rightEnd( (*m_endPoint)[Right]->GetSample(),
1694 (*m_endPoint)[Right]->GetLine() );
1695
1696 // Convert these to screen coordinates for updating the rubberband
1697 QList< QList<QPoint> > rubberBandVertices;
1698 QList<QPoint> rubberBand1;
1699 int sx, sy, ex, ey;
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) );
1706
1707 rubberBandVertices.push_back(rubberBand1);
1708
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) );
1716
1717 rubberBandVertices.push_back(rubberBand2);
1718
1719 // Create line for left image
1720 QLineF leftProfile(leftStart,leftEnd);
1721 QLineF rightProfile(rightStart,rightEnd);
1722
1723 // Determine shortest line, we will step through shortest line,
1724 // finding the matching position on the longer line.
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;
1732 }
1733 else {
1734 longProfile = rightProfile;
1735 longCube = m_rightCube;
1736 shortProfile = leftProfile;
1737 shortCube = m_leftCube;
1738 }
1739
1740 QVector<QPointF> profileData;
1741 double elevation = 0.;
1742 double elevationError = 0.;
1743
1744 Pvl regDef = m_pointEditor->templateFileName();
1745 AutoReg *ar = AutoRegFactory::Create(regDef);
1746
1747 int failureCount = 0;
1748 QApplication::setOverrideCursor(Qt::WaitCursor);
1749
1750 for (int i = 0; i <= (int) shortProfile.length(); i++) {
1751 double shortSamp=0, shortLine=0, longSamp=0, longLine=0;
1752 try {
1753 shortSamp = shortProfile.pointAt( 1/shortProfile.length() * i ).x();
1754 shortLine = shortProfile.pointAt( 1/shortProfile.length() * i ).y();
1755
1756 longSamp = longProfile.pointAt( 1/shortProfile.length() * i ).x();
1757 longLine = longProfile.pointAt( 1/shortProfile.length() * i ).y();
1758
1759 // Coreg
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 );
1764 ar->Register();
1765// AutoReg::RegisterStatus status = ar->Register();
1766 if ( ar->Success() ) {
1767 longSamp = ar->CubeSample();
1768 longLine = ar->CubeLine();
1769
1770 // If the local radius combo box is set to DEM, get the dem radius
1771 // First, SetImage using the Elevation model, before turning off
1772 // to get camera angles.
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;
1783 }
1784 }
1785
1786 shortCube->camera()->IgnoreElevationModel(true);
1787 longCube->camera()->IgnoreElevationModel(true);
1788
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) );
1796// elevations.push_back(elevation);
1797// pixels.push_back(i);
1798 }
1799 else {
1800 failureCount++;
1801 }
1802 }
1803 catch (IException &e) {
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();
1812 }
1813
1814 }
1815 QApplication::restoreOverrideCursor();
1816
1817// cout<<"Registration attempts = "<<(int)shortLength<<" failures = "<<failureCount<<endl;
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);
1828
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);
1834 return;
1835 }
1836 PlotWindow *plotWindow = selectedWindow(true);
1837 plotWindow->setAxisLabel(0,"Elevation (meters)");
1840// plotCurve->setData(&pixels[0], &elevations[0], pixels.size() );
1841 plotCurve->setData( new QwtPointSeriesData(profileData) );
1842 plotCurve->setTitle("Elevations (Meters)");
1843 plotCurve->setPen( QPen(Qt::white) );
1844 plotCurve->setColor(Qt::white);
1845 // Create vertices for rubberband based on refined profile end points
1846
1847 // TODO: This needs to be changed to band displayed???
1848 QList<int> bands;
1849 bands.push_back(1);
1850 bands.push_back(1);
1851 plotCurve->setSource(m_linkedViewports, rubberBandVertices, bands);
1852 plotWindow->add(plotCurve);
1853
1854 delete m_profileDialog;
1855 m_profileDialog = NULL;
1856// m_startPoint = NULL;
1857// m_endPoint = NULL;
1858// rubberBandTool()->clear();
1859
1860 }
1861
1862
1863
1864 void StereoTool::updateLabels() {
1865 // Empty elevation info if nothing there
1866 QString elevationLabel, elevationErrorLabel;
1867 QString baseRadiiLabel, leftDemRadiiLabel, rightDemRadiiLabel;
1868 if ( m_editPoint->GetMeasure(Left)->GetFocalPlaneMeasuredX() != Isis::Null ) {
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 );
1877
1878 Camera *leftCamera = m_leftCube->camera();
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);
1885
1886 Camera *rightCamera = m_rightCube->camera();
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);
1893 }
1894 else {
1895 elevationLabel = "Elevation: ";
1896 elevationErrorLabel = "Elevation Error: ";
1897 baseRadiiLabel = "Local Radii: ";
1898 leftDemRadiiLabel = "Left DEM Radii: ";
1899 rightDemRadiiLabel = "Right DEM Radii: ";
1900 }
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);
1906 }
1907
1908
1909
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();
1915
1916 }
1917
1918
1919
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);
1925
1926 }
1927}
Parent class for plotting tools which provides common functionality.
PlotWindow * selectedWindow(bool createIfNeeded=true)
Get the 'active' plot window (the window selected by the user to contain new curves).
virtual void paintViewport(MdiCubeViewport *vp, QPainter *painter)
This method allows each plot window to paint any information it wants onto the cube viewports.
QWidget * createToolBarWidget(QStackedWidget *parent)
This provides the standard plot tool options, such as selecting an active plot window.
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
static QString UserName()
Returns the user name.
static AutoReg * Create(Pvl &pvl)
Create an AutoReg object using a PVL specification.
Auto Registration class.
Definition AutoReg.h:167
virtual bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition Camera.cpp:156
a control measurement
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
@ Manual
Hand Measured (e.g., qnet)
a control network
Definition ControlNet.h:258
Point Editor Widget.
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.
A single control point.
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.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:1740
Camera * camera()
Return a camera associated with the cube.
Definition Cube.cpp:1457
int sampleCount() const
Definition Cube.cpp:1813
virtual QString fileName() const
Returns the opened cube's filename.
Definition Cube.cpp:1569
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.
Definition Distance.h:34
bool isValid() const
Test if this distance has been initialized or not.
Definition Distance.cpp:192
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
double meters() const
Get the distance in meters.
Definition Distance.cpp:85
File name manipulation and expansion.
Definition FileName.h:100
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
Adds specific functionality to C++ strings.
Definition IString.h:165
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
Cube display widget for certain Isis MDI applications.
@ Elevation
The data is an elevation (in meters).
Definition PlotCurve.h:71
@ PixelNumber
The data is a pixel #.
Definition PlotCurve.h:79
PvlEditDialog creates a QDialog window in which a QTextEdit box displays the contents of a pvl file.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
void setDrawActiveViewportOnly(bool activeOnly=false)
This called to set whether rubber band is drawn on active viewport only rather than all linked viewpo...
void enable(RubberBandMode mode, bool showIndicatorColors=false)
This is called when changing modes or turning on.
void clear()
clears the rubber band!
void IgnoreElevationModel(bool ignore)
This allows you to ignore the cube elevation model and use the ellipse.
Definition Sensor.cpp:62
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.
Definition Spice.cpp:1380
QAction * toolPadAction(ToolPad *pad)
Put the StereoTool icon on the main window Toolpad.
void measureSaved()
Save control measures under crosshairs of ChipViewports.
void createPoint(double lat, double lon)
Create control point at given lat,lon.
void detachCurves()
This will be called when the selected plot window changes.
StereoTool(QWidget *parent)
Construct the StereoTool.
void modifyPoint(ControlPoint *point)
Modify given control point.
void setTemplateFile()
Allows user to set a new template file.
void deletePoint(ControlPoint *point)
Delete given control point.
void loadPoint()
Load control point into the ControlPointEdit widget.
void viewTemplateFile()
Allows the user to view the template file that is currently set.
void enableRubberBandTool()
This methods enables the RubberBandTool, it also sets the RubberBandTool to allow points and to allow...
void createStereoTool(QWidget *parent)
Design the StereoTool widget.
QWidget * createToolBarWidget(QStackedWidget *parent)
Attaches this tool to the toolbar.
void createMenus()
Create the menus for StereoTool.
PlotWindow * createWindow()
This needs to be implemented by children to instantiate a plot window of the appropriate child class ...
void paintAllViewports()
This method will repaint the control measures in each viewport.
void setFiles(Cube *leftCube, Cube *rightCube)
Setup the stereo cubes.
void paintViewport(MdiCubeViewport *cvp, QPainter *painter)
Repaint the given CubeViewport.
void saveAsElevations()
Save the elevation information to file.
void clearFiles()
New files selected, clean up old file info.
Pixel value mapper.
Definition Stretch.h:58
This class defines a body-fixed surface point.
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
Definition Target.cpp:428
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition Tool.cpp:390
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition Tool.h:197
QString toolIconDir() const
returns the path to the icon directory.
Definition Tool.h:113
Universal Ground Map.
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.
Definition Apollo.h:16
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.