Isis 3 Programmer Reference
AdvancedTrackTool.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "AdvancedTrackTool.h"
10
11#include <QAction>
12#include <QApplication>
13#include <QLabel>
14#include <QListIterator>
15#include <QMenu>
16#include <QMenuBar>
17#include <QMessageBox>
18#include <QPushButton>
19#include <QScrollArea>
20#include <QSize>
21#include <QTableWidget>
22#include <QTableWidgetItem>
23#include <QToolBar>
24#include <QVBoxLayout>
25
26#include "Angle.h"
27#include "Camera.h"
28#include "CameraDistortionMap.h"
29#include "CameraFocalPlaneMap.h"
30#include "Distance.h"
31#include "iTime.h"
32#include "Longitude.h"
33#include "MdiCubeViewport.h"
34#include "Projection.h"
35#include "RingPlaneProjection.h"
36#include "SerialNumber.h"
37#include "SpecialPixel.h"
38#include "TableMainWindow.h"
39#include "Target.h"
40#include "TProjection.h"
41#include "TrackingTable.h"
42
43namespace Isis {
44
45 // For mosaic tracking
46#define FLOAT_MIN -16777215
47
54 p_tableWin = new TableMainWindow("Advanced Tracking", parent);
56 connect(p_tableWin, SIGNAL(fileLoaded()), this, SLOT(updateID()));
57
58 p_action = new QAction(parent);
59 p_action->setText("Tracking ...");
60 p_action->setIcon(QPixmap(toolIconDir() + "/goto.png"));
61 p_action->setShortcut(Qt::CTRL + Qt::Key_T);
62 p_action->setWhatsThis("<b>Function: </b> Opens the Advanced Tracking Tool \
63 window. This window will track sample/line positions,\
64 lat/lon positions, and many other pieces of \
65 information. All of the data in the window can be \
66 saved to a text file. <p><b>Shortcut: </b> Ctrl+T</p>");
67 connect(p_action, SIGNAL(triggered()), p_tableWin, SLOT(showTable()));
68 activate(true);
69 connect(p_action, SIGNAL(triggered()), p_tableWin, SLOT(raise()));
70 connect(p_action, SIGNAL(triggered()), p_tableWin, SLOT(syncColumns()));
71 p_tableWin->installEventFilter(this);
72
73 // Adds each item of checkBoxItems to the table.
74 // If a tool tip is specified, we cannot skip parameters, so -1 and
75 // Qt::Horizontal are specified.
76 QList< QList<QString> >::iterator iter;
77 for (iter = checkBoxItems.begin(); iter != checkBoxItems.end(); ++iter) {
78 QList<QString> currentList = *iter;
79 QString header = currentList[0];
80 QString menuText = currentList[2];
81 QString toolTip = currentList[3];
82 bool onByDefault;
83 if (currentList[1] == QString("true")) {
84 onByDefault = true;
85 }
86 else {
87 onByDefault = false;
88 }
89
90 if (toolTip != QString("")) {
91 p_tableWin->addToTable(onByDefault, header, menuText,
92 -1, Qt::Horizontal, toolTip);
93 }
94 else {
95 p_tableWin->addToTable(onByDefault, header, menuText);
96 }
97 }
98
99 //This variable will keep track of how many times
100 // the user has issued the 'record' command.
101 p_id = 0;
102
103 // Setup 10 blank rows in the table
104 for(int r = 0; r < 10; r++) {
105 p_tableWin->table()->insertRow(r);
106 for(int c = 0; c < p_tableWin->table()->columnCount(); c++) {
107 QTableWidgetItem *item = new QTableWidgetItem("");
108 p_tableWin->table()->setItem(r, c, item);
109 }
110 }
111
112 // Create the action for recording points
113 QAction *recordAction = new QAction(parent);
114 recordAction->setShortcut(Qt::Key_R);
115 parent->addAction(recordAction);
116 connect(recordAction, SIGNAL(triggered()), this, SLOT(record()));
117 p_tableWin->setStatusMessage("To record press the R key"
118 " --- Double click on a cell to enable crtl+c (copy) and"
119 " ctrl+v (paste).");
120
121 // Add a help menu to the menu bar
122 QMenuBar *menuBar = p_tableWin->menuBar();
123 QMenu *helpMenu = menuBar->addMenu("&Help");
124 QAction *help = new QAction(p_tableWin);
125 help->setText("&Tool Help");
126 help->setShortcut(Qt::CTRL + Qt::Key_H);
127 connect(help, SIGNAL(triggered()), this, SLOT(helpDialog()));
128 helpMenu->addAction(help);
129 p_tableWin->setMenuBar(menuBar);
130 installEventFilter(p_tableWin);
131
132 m_showHelpOnStart = true;
133 readSettings();
134 }
135
145 if(e->type() == QEvent::Show) {
146 activate(true);
147 if (m_showHelpOnStart) {
148 helpDialog();
149 m_showHelpOnStart = false;
151 }
152 }
153 else if(e->type() == QEvent::Hide) {
154 activate(false);
155 }
156 return Tool::eventFilter(o, e);
157 }
158
159
166 menu->addAction(p_action);
167 }
168
176 perm->addAction(p_action);
177 }
178
186 updateRow(p);
187 }
188
195
196 if(cubeViewport()->isLinked()) {
197 for(int i = 0; i < p_numRows; i++) {
199 }
200 }
201 else {
203 }
204
205 }
206
214 if(cvp == NULL) {
216 return;
217 }
218
219 if(!cubeViewport()->isLinked()) {
220 updateRow(cvp, p, p_tableWin->currentRow());
221 p_numRows = 1;
222 }
223 else {
224 p_numRows = 0;
225 for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
226 MdiCubeViewport *d = (*(cubeViewportList()))[i];
227 if(d->isLinked()) {
229 p_numRows++;
230 }
231 }
232 }
233 }
234
235
244 int AdvancedTrackTool::getIndex(QString keyword) {
245 int index = 0;
246 QList< QList<QString> >::iterator iter;
247 for (iter = checkBoxItems.begin(); iter != checkBoxItems.end(); ++iter) {
248 QList<QString> currentList = *iter;
249 QList<QString> splitHeader = currentList[0].split(":");
250 QList<QString>::iterator headerIter;
251 for (headerIter = splitHeader.begin(); headerIter != splitHeader.end(); ++headerIter) {
252 QString header = *headerIter;
253 if (header.toLower() == keyword.toLower()) {
254 return index;
255 }
256 index++;
257 }
258 }
259 IString msg = "Header [" + keyword + "] not found; make sure spelling is correct";
260 throw IException(IException::Io, msg, _FILEINFO_);
261 }
262
270 void AdvancedTrackTool::updateRow(MdiCubeViewport *cvp, QPoint p, int row) {
271 // Get the sample line position to report
272 double sample, line;
273 cvp->viewportToCube(p.x(), p.y(), sample, line);
274 int isample = int (sample + 0.5);
275 int iline = int (line + 0.5);
276
277 /*if there are linked cvp's then we want to highlight (select)
278 the row of the active cvp.*/
279 if(cvp->isLinked()) {
280
281 if(cvp == cubeViewport()) {
282 p_tableWin->table()->selectRow(row);
283 }
284
285 }
286
287
288 // Do we need more rows?
289 if(row + 1 > p_tableWin->table()->rowCount()) {
290 p_tableWin->table()->insertRow(row);
291 for(int c = 0; c < p_tableWin->table()->columnCount(); c++) {
292 QTableWidgetItem *item = new QTableWidgetItem("");
293 p_tableWin->table()->setItem(row, c, item);
294 if(c == 0) p_tableWin->table()->scrollToItem(item);
295 }
296 }
297
298 // Blank out the row to remove stuff left over from previous cvps
299 for(int c = 0; c < p_tableWin->table()->columnCount(); c++) {
300 p_tableWin->table()->item(row, c)->setText("");
301 }
302
303 // Don't write anything if we are outside the cube
304 if(sample < 0.5) return;
305 if(line < 0.5) return;
306 if(sample > cvp->cubeSamples() + 0.5) return;
307 if(line > cvp->cubeLines() + 0.5) return;
308
309 // Write cols 0-2 (id, sample, line)
310 p_tableWin->table()->item(row, getIndex("ID"))->setText(QString::number(p_id));
311 p_tableWin->table()->item(row, getIndex("Sample"))->setText(QString::number(sample));
312 p_tableWin->table()->item(row, getIndex("Line"))->setText(QString::number(line));
313
314 // Write col 3 (band)
315 if (cvp->isGray()) {
316 p_tableWin->table()->item(row, getIndex("Band"))->setText(QString::number(cvp->grayBand()));
317 }
318 else {
319 p_tableWin->table()->item(row, getIndex("Band"))->setText(QString::number(cvp->redBand()));
320 }
321
322 // Write out the path, filename, and serial number
323 FileName fname = FileName(cvp->cube()->fileName()).expanded();
324 QString fnamePath = fname.path();
325 QString fnameName = fname.name();
326 p_tableWin->table()->item(row, getIndex("Path"))->setText(fnamePath);
327 p_tableWin->table()->item(row, getIndex("FileName"))->setText(fnameName);
328 if (!cvp->cube()->hasGroup("Tracking") && !cvp->cube()->hasTable("InputImages")){
329 p_tableWin->table()->item(row, getIndex("Serial Number"))->setText(SerialNumber::Compose(*cvp->cube()));
330 }
331
332 // If we are outside of the image then we are done
333 if((sample < 0.5) || (line < 0.5) ||
334 (sample > cvp->cubeSamples() + 0.5) ||
335 (line > cvp->cubeLines() + 0.5)) {
336 return;
337 }
338
339 // Otherwise write out col 4 (Pixel value)
340 QString pixel;
341 if(cvp->isGray()) {
342 pixel = PixelToString(cvp->grayPixel(isample, iline), 12);
343 }
344 else {
345 pixel = PixelToString(cvp->redPixel(isample, iline), 12);
346 }
347 p_tableWin->table()->item(row, getIndex("Pixel"))->setText(pixel);
348
349 // Do we have a camera model?
350 if(cvp->camera() != NULL) {
351 if(cvp->camera()->SetImage(sample, line)) {
352 if (cvp->camera()->target()->isSky()) {
353 double dec = cvp->camera()->Declination();
354 double ra = cvp->camera()->RightAscension();
355 p_tableWin->table()->item(row, getIndex("Right Ascension"))->
356 setText(QString::number(ra, 'f', 15));
357 p_tableWin->table()->item(row, getIndex("Declination"))->
358 setText(QString::number(dec, 'f', 15));
359 }
360 else {
361 // Write columns ocentric lat/lon, and radius, only if set image succeeds
362 double lat = cvp->camera()->UniversalLatitude();
363 double lon = cvp->camera()->UniversalLongitude();
364
365 double radius = cvp->camera()->LocalRadius().meters();
366 p_tableWin->table()->item(row, getIndex("Planetocentric Latitude"))->
367 setText(QString::number(lat, 'f', 15));
368 p_tableWin->table()->item(row, getIndex("360 Positive East Longitude"))->
369 setText(QString::number(lon, 'f', 15));
370 p_tableWin->table()->item(row, getIndex("Local Radius"))->
371 setText(QString::number(radius, 'f', 15));
372
373 /* 180 Positive East Lon. */
374 p_tableWin->table()->item(row, getIndex("180 Positive East Longitude"))->
375 setText(QString::number(TProjection::To180Domain(lon), 'f', 15));
376
377 // Write out the planetographic and positive west values, only if set image succeeds
378 lon = -lon;
379 while(lon < 0.0) lon += 360.0;
380 Distance radii[3];
381 cvp->camera()->radii(radii);
382 lat = TProjection::ToPlanetographic(lat, radii[0].meters(), radii[2].meters());
383 p_tableWin->table()->item(row, getIndex("Planetographic Latitude"))->
384 setText(QString::number(lat, 'f', 15));
385 p_tableWin->table()->item(row, getIndex("360 Positive West Longitude"))->
386 setText(QString::number(lon, 'f', 15));
387
388 /*180 Positive West Lon. */
389 p_tableWin->table()->item(row, getIndex("180 Positive West Longitude"))->setText(
390 QString::number(TProjection::To180Domain(lon), 'f', 15));
391
392 // Next write out columns, the x/y/z position of the lat/lon, only if set image succeeds
393 double pos[3];
394 cvp->camera()->Coordinate(pos);
395 p_tableWin->table()->item(row, getIndex("Point X"))->setText(QString::number(pos[0]));
396 p_tableWin->table()->item(row, getIndex("Point Y"))->setText(QString::number(pos[1]));
397 p_tableWin->table()->item(row, getIndex("Point Z"))->setText(QString::number(pos[2]));
398
399 // Write out columns resolution, only if set image succeeds
400 double res = cvp->camera()->PixelResolution();
401 if (res != -1.0) {
402 p_tableWin->table()->item(row, getIndex("Resolution"))->setText(QString::number(res));
403 }
404 else {
405 p_tableWin->table()->item(row, getIndex("Resolution"))->setText("");
406 }
407
408 // Write out columns, oblique pixel resolution, only if set image succeeds
409 double obliquePRes = cvp->camera()->ObliquePixelResolution();
410 if (obliquePRes != Isis::Null) {
411 p_tableWin->table()->item(row, getIndex("Oblique Pixel Resolution"))->
412 setText(QString::number(obliquePRes));
413 }
414 else {
415 p_tableWin->table()->item(row, getIndex("Oblique Pixel Resolution"))->setText("");
416 }
417
418 // Write out columns photometric angle values, only if set image succeeds
419 double phase = cvp->camera()->PhaseAngle();
420 p_tableWin->table()->item(row, getIndex("Phase"))->setText(QString::number(phase));
421 double incidence = cvp->camera()->IncidenceAngle();
422 p_tableWin->table()->item(row, getIndex("Incidence"))->setText(QString::number(incidence));
423 double emission = cvp->camera()->EmissionAngle();
424 p_tableWin->table()->item(row, getIndex("Emission"))->setText(QString::number(emission));
425
426 // Write out columns local incidence and emission, only if set image
427 // succeeds. This might fail if there are holes in the DEM.
428 // Calculates the angles local to the slope for the DEMs, compare against
429 // the incidence and emission angles calculated for the sphere
430 Angle phaseAngle, incidenceAngle, emissionAngle;
431 bool bSuccess = false;
432 cvp->camera()->LocalPhotometricAngles(phaseAngle, incidenceAngle, emissionAngle, bSuccess);
433 if(bSuccess) {
434 p_tableWin->table()->item(row, getIndex("LocalIncidence"))->
435 setText(QString::number(incidenceAngle.degrees()));
436 p_tableWin->table()->item(row, getIndex("LocalEmission"))->
437 setText(QString::number(emissionAngle.degrees()));
438 }
439 else {
440 p_tableWin->table()->item(row, getIndex("LocalIncidence"))->setText("");
441 p_tableWin->table()->item(row, getIndex("LocalEmission"))->setText("");
442 }
443
444 // If set image succeeds, write out columns north azimuth, sun azimuth, solar longitude
445 // north azimuth is meaningless for ring plane projections
446 double northAzi = cvp->camera()->NorthAzimuth();
447 if (cvp->camera()->target()->shape()->name() != "Plane"
448 && Isis::IsValidPixel(northAzi)) {
449 p_tableWin->table()->item(row, getIndex("North Azimuth"))->
450 setText(QString::number(northAzi));
451 }
452 else { // north azimuth is meaningless for ring plane projections
453 p_tableWin->table()->item(row, getIndex("North Azimuth"))->setText("");
454 }
455
456
457 try {
458 double sunAzi = cvp->camera()->SunAzimuth();
459 if (Isis::IsValidPixel(sunAzi)) {
460 p_tableWin->table()->item(row, getIndex("Sun Azimuth"))->
461 setText(QString::number(sunAzi));
462 }
463 else { // sun azimuth is null
464 p_tableWin->table()->item(row, getIndex("Sun Azimuth"))->setText("");
465 }
466 }
467 catch(IException &e) {
468 p_tableWin->table()->item(row, getIndex("Sun Azimuth"))->setText("");
469 }
470
471
472 double spacecraftAzi = cvp->camera()->SpacecraftAzimuth();
473 if (Isis::IsValidPixel(spacecraftAzi)) {
474 p_tableWin->table()->item(row, getIndex("Spacecraft Azimuth"))->
475 setText(QString::number(spacecraftAzi));
476 }
477 else { // spacecraft azimuth is null
478 p_tableWin->table()->item(row, getIndex("Spacecraft Azimuth"))->setText("");
479 }
480
481 // Write out columns solar lon, slant distance, local solar time
482 try {
483 double solarLon = cvp->camera()->solarLongitude().degrees();
484 p_tableWin->table()->item(row, getIndex("Solar Longitude"))->
485 setText(QString::number(solarLon));
486 }
487 catch (IException &e) {
488 p_tableWin->table()->item(row, getIndex("Solar Longitude"))->
489 setText("");
490 }
491
492 double slantDistance = cvp->camera()->SlantDistance();
493 p_tableWin->table()->item(row, getIndex("Slant Distance"))->
494 setText(QString::number(slantDistance));
495 try {
496 double lst = cvp->camera()->LocalSolarTime();
497 p_tableWin->table()->item(row, getIndex("Local Solar Time"))->
498 setText(QString::number(lst));
499 }
500 catch (IException &e) {
501 p_tableWin->table()->item(row, getIndex("Local Solar Time"))->
502 setText("");
503 }
504 }
505
506 } // end if set image succeeds
507
508 // Always write out the x/y/z of the undistorted focal plane
509 if (cvp->camera()->DistortionMap() != NULL) {
510 CameraDistortionMap *distortedMap = cvp->camera()->DistortionMap();
511 double undistortedFocalPlaneX = distortedMap->UndistortedFocalPlaneX();
512 p_tableWin->table()->item(row, getIndex("Undistorted Focal X"))->
513 setText(QString::number(undistortedFocalPlaneX));
514 double undistortedFocalPlaneY = distortedMap->UndistortedFocalPlaneY();
515 p_tableWin->table()->item(row, getIndex("Undistorted Focal Y"))->
516 setText(QString::number(undistortedFocalPlaneY));
517 double undistortedFocalPlaneZ = distortedMap->UndistortedFocalPlaneZ();
518 p_tableWin->table()->item(row, getIndex("Undistorted Focal Z"))->
519 setText(QString::number(undistortedFocalPlaneZ));
520 }
521 else {
522 p_tableWin->table()->item(row, getIndex("Undistorted Focal X"))->
523 setText("");
524 p_tableWin->table()->item(row, getIndex("Undistorted Focal Y"))->
525 setText("");
526 p_tableWin->table()->item(row, getIndex("Undistorted Focal Z"))->
527 setText("");
528 }
529
530 // Always write out the x/y of the distorted focal plane
531 if (cvp->camera()->FocalPlaneMap() != NULL) {
532 CameraFocalPlaneMap *focalPlaneMap = cvp->camera()->FocalPlaneMap();
533 double distortedFocalPlaneX = focalPlaneMap->FocalPlaneX();
534 p_tableWin->table()->item(row, getIndex("Focal Plane X"))->
535 setText(QString::number(distortedFocalPlaneX));
536 double distortedFocalPlaneY = focalPlaneMap->FocalPlaneY();
537 p_tableWin->table()->item(row, getIndex("Focal Plane Y"))->
538 setText(QString::number(distortedFocalPlaneY));
539 }
540 else {
541 p_tableWin->table()->item(row, getIndex("Focal Plane X"))->
542 setText("");
543 p_tableWin->table()->item(row, getIndex("Focal Plane Y"))->
544 setText("");
545 }
546
547
548 // Always write out columns ra/dec, regardless of whether set image succeeds
549 double ra = cvp->camera()->RightAscension();
550 p_tableWin->table()->item(row, getIndex("Right Ascension"))->setText(QString::number(ra));
551 double dec = cvp->camera()->Declination();
552 p_tableWin->table()->item(row, getIndex("Declination"))->setText(QString::number(dec));
553
554 // Always write out columns et and utc, regardless of whether set image succeeds
555 iTime time(cvp->camera()->time());
556 p_tableWin->table()->item(row, getIndex("Ephemeris Time"))->
557 setText(QString::number(time.Et(), 'f', 15));
558 QString time_utc = time.UTC();
559 p_tableWin->table()->item(row, getIndex("UTC"))->setText(time_utc);
560
561 // Always out columns spacecraft position, regardless of whether set image succeeds
562 double pos[3];
563 cvp->camera()->instrumentPosition(pos);
564 p_tableWin->table()->item(row, getIndex("Spacecraft X"))->setText(QString::number(pos[0]));
565 p_tableWin->table()->item(row, getIndex("Spacecraft Y"))->setText(QString::number(pos[1]));
566 p_tableWin->table()->item(row, getIndex("Spacecraft Z"))->setText(QString::number(pos[2]));
567 }
568
569 else if (cvp->projection() != NULL) {
570 // Determine the projection type
571 Projection::ProjectionType projType = cvp->projection()->projectionType();
572
573 if (cvp->projection()->SetWorld(sample, line)) {
574 if (projType == Projection::Triaxial) {
575 TProjection *tproj = (TProjection *) cvp->projection();
576 double lat = tproj->UniversalLatitude();
577 double lon = tproj->UniversalLongitude();
578
579 double glat = tproj->ToPlanetographic(lat);
580 double wlon = -lon;
581 while(wlon < 0.0) wlon += 360.0;
582 if (tproj->IsSky()) {
583 lon = tproj->Longitude();
584 p_tableWin->table()->item(row, getIndex("Right Ascension"))->
585 setText(QString::number(lon, 'f', 15));
586 p_tableWin->table()->item(row, getIndex("Declination"))->
587 setText(QString::number(lat, 'f', 15));
588 }
589 else {
590 double radius = tproj->LocalRadius();
591 p_tableWin->table()->item(row, getIndex("Planetocentric Latitude"))->
592 setText(QString::number(lat, 'f', 15));
593 p_tableWin->table()->item(row, getIndex("Planetographic Latitude"))->
594 setText(QString::number(glat, 'f', 15));
595 p_tableWin->table()->item(row, getIndex("360 Positive East Longitude"))->
596 setText(QString::number(lon, 'f', 15));
597 p_tableWin->table()->item(row, getIndex("180 Positive East Longitude"))->
598 setText(QString::number(TProjection::To180Domain(lon), 'f', 15));
599 p_tableWin->table()->item(row, getIndex("360 Positive West Longitude"))->
600 setText(QString::number(wlon, 'f', 15));
601 p_tableWin->table()->item(row, getIndex("180 Positive East Longitude"))->
602 setText(QString::number(TProjection::To180Domain(wlon), 'f', 15));
603 p_tableWin->table()->item(row, getIndex("Local Radius"))->setText(QString::number(radius, 'f', 15));
604 }
605 }
606 else { // RingPlane
607 RingPlaneProjection *rproj = (RingPlaneProjection *) cvp->projection();
608 double lat = rproj->UniversalRingRadius();
609 double lon = rproj->UniversalRingLongitude();
610
611 double wlon = -lon;
612 while(wlon < 0.0) wlon += 360.0;
613 double radius = lat;
614 p_tableWin->table()->item(row, getIndex("Planetocentric Latitude"))->setText("0.0");
615 p_tableWin->table()->item(row, getIndex("Planetographic Latitude"))->setText("0.0");
616 p_tableWin->table()->item(row, getIndex("360 Positive East Longitude"))->
617 setText(QString::number(lon, 'f', 15));
618 p_tableWin->table()->item(row, getIndex("180 Positive East Longitude"))->
619 setText(QString::number(RingPlaneProjection::To180Domain(lon), 'f', 15));
620 p_tableWin->table()->item(row, getIndex("360 Positive West Longitude"))->
621 setText(QString::number(wlon, 'f', 15));
622 p_tableWin->table()->item(row, getIndex("180 Positive West Longitude"))->
623 setText(QString::number(RingPlaneProjection::To180Domain(wlon), 'f', 15));
624 p_tableWin->table()->item(row, getIndex("Local Radius"))->
625 setText(QString::number(radius, 'f', 15));
626 }
627 }
628 }
629
630 //If there is a projection add the Projected X and Y coords to the table
631 if(cvp->projection() != NULL) {
632 if(cvp->projection()->SetWorld(sample, line)) {
633 double projX = cvp->projection()->XCoord();
634 double projY = cvp->projection()->YCoord();
635 p_tableWin->table()->item(row, getIndex("Projected X"))->
636 setText(QString::number(projX, 'f', 15));
637 p_tableWin->table()->item(row, getIndex("Projected Y"))->
638 setText(QString::number(projY, 'f', 15));
639 }
640 }
641
642 // Track the Mosaic Origin - Index (Zero based) and FileName
643 if (cvp->cube()->hasTable("InputImages") || cvp->cube()->hasGroup("Tracking")) {
644 int iMosaicOrigin = -1;
645 QString sSrcFileName = "";
646 QString sSrcSerialNum = "";
647 TrackMosaicOrigin(cvp, iline, isample, iMosaicOrigin, sSrcFileName, sSrcSerialNum);
648 p_tableWin->table()->item(row, getIndex("Track Mosaic Index"))->
649 setText(QString::number(iMosaicOrigin));
650 p_tableWin->table()->item(row, getIndex("Track Mosaic FileName"))->
651 setText(QString(sSrcFileName));
652 p_tableWin->table()->item(row, getIndex("Track Mosaic Serial Number"))->
653 setText(QString(sSrcSerialNum));
654 }
655 }
656
657
675 int piSample, int &piOrigin, QString &psSrcFileName,
676 QString &psSrcSerialNum) {
677 try {
678 Cube *cCube = cvp->cube();
679 int iTrackBand = -1;
680
681 // This is a mosaic in the new format or the external tracking cube itself
682 if(cCube->hasGroup("Tracking") ||
683 (cCube->hasTable(trackingTableName) && cCube->bandCount() == 1)) {
684 Cube *trackingCube;
685 if(cCube->hasGroup("Tracking")) {
686 trackingCube = cvp->trackingCube();
687 }
688 else {
689 trackingCube = cCube;
690 }
691
692 // Read the cube DN value from TRACKING cube at location (piLine, piSample)
693 Portal trackingPortal(trackingCube->sampleCount(), 1, trackingCube->pixelType());
694 trackingPortal.SetPosition(piSample, piLine, 1);
695 trackingCube->read(trackingPortal);
696
697 unsigned int currentPixel = trackingPortal[0];
698 if (currentPixel != NULLUI4) { // If from an image
699 Table table = trackingCube->readTable(trackingTableName); // trackingTableName from TrackingTable
700 TrackingTable trackingTable(table);
701
702 FileName trackingFileName = trackingTable.pixelToFileName(currentPixel);
703 psSrcFileName = trackingFileName.name();
704 psSrcSerialNum = trackingTable.pixelToSN(currentPixel);
705 piOrigin = trackingTable.fileNameToIndex(trackingFileName, psSrcSerialNum);
706 }
707 }
708 // Backwards compatability. Have this tool work with attached TRACKING bands
709 else if(cCube->hasTable(trackingTableName)) {
710 Pvl *cPvl = cCube->label();
711 PvlObject cObjIsisCube = cPvl->findObject("IsisCube");
712 PvlGroup cGrpBandBin = cObjIsisCube.findGroup("BandBin");
713 for(int i = 0; i < cGrpBandBin.keywords(); i++) {
714 PvlKeyword &cKeyTrackBand = cGrpBandBin[i];
715 for(int j = 0; j < cKeyTrackBand.size(); j++) {
716 if(cKeyTrackBand[j] == "TRACKING") {
717 iTrackBand = j;
718 break;
719 }
720 }
721 }
722
723 if(iTrackBand > 0 && iTrackBand <= cCube->bandCount()) {
724 Portal cOrgPortal(cCube->sampleCount(), 1,
725 cCube->pixelType());
726 cOrgPortal.SetPosition(piSample, piLine, iTrackBand + 1); // 1 based
727 cCube->read(cOrgPortal);
728 piOrigin = (int)cOrgPortal[0];
729 switch(SizeOf(cCube->pixelType())) {
730 case 1:
731 piOrigin -= VALID_MIN1;
732 break;
733
734 case 2:
735 piOrigin -= VALID_MIN2;
736 break;
737
738 case 4:
739 piOrigin -= FLOAT_MIN;
740 break;
741 }
742
743 // Get the input file name and serial number
744 Table cFileTable = cCube->readTable(trackingTableName);
745 int iRecs = cFileTable.Records();
746 if(piOrigin >= 0 && piOrigin < iRecs) {
747 psSrcFileName = QString(cFileTable[piOrigin][0]);
748 psSrcSerialNum = QString(cFileTable[piOrigin][1]);
749 }
750 }
751 }
752
753 }
754 catch (IException &e) {
755 // This gets called too frequently to raise a warning; so, suppress the error
756 // and return invalid.
757 piOrigin = -1;
758 }
759
760 if (piOrigin == -1) { // If not from an image, display N/A
761 psSrcFileName = "N/A";
762 psSrcSerialNum = "N/A";
763 }
764 }
765
766
773
775
776 QVBoxLayout *dialogLayout = new QVBoxLayout;
777 helpDialog->setLayout(dialogLayout);
778 QLabel *dialogTitle = new QLabel("<h3>Advanced Tracking Tool</h3>");
779 dialogLayout->addWidget(dialogTitle);
780
781 QTabWidget *tabArea = new QTabWidget;
782 dialogLayout->addWidget(tabArea);
783
784 QScrollArea *recordTab = new QScrollArea;
785 QWidget *recordContainer = new QWidget;
786 QVBoxLayout *recordLayout = new QVBoxLayout;
787 recordContainer->setLayout(recordLayout);
788 QLabel *recordText = new QLabel("To record, click on the viewport of interest and"
789 " press (r) while the mouse is hovering over the image.");
790 recordText->setWordWrap(true);
791 recordLayout->addWidget(recordText);
792 recordTab->setWidget(recordContainer);
793
794 QScrollArea *helpTab = new QScrollArea;
795 QWidget *helpContainer = new QWidget;
796 QVBoxLayout *helpLayout = new QVBoxLayout;
797 helpContainer->setLayout(helpLayout);
798 QLabel *helpText = new QLabel("In order to use <i>ctrl+c</i> to copy and <i>ctrl+v</i> to"
799 " paste, you need to double click on the cell you are copying"
800 " from (the text should be highlighted). Then double click on"
801 " the cell you are pasting to (you should see a cursor if the"
802 " cell is blank). When a cell is in this editing mode, most"
803 " keyboard shortcuts work.");
804 helpText->setWordWrap(true);
805 recordText->setWordWrap(true);
806 helpLayout->addWidget(helpText);
807 helpTab->setWidget(helpContainer);
808
809 tabArea->addTab(recordTab, "Record");
810 tabArea->addTab(helpTab, "Table Help");
811
812 QPushButton *okButton = new QPushButton("OK");
813 dialogLayout->addStretch();
814 dialogLayout->addWidget(okButton);
815 helpDialog->show();
816 connect(okButton, SIGNAL(clicked()), helpDialog, SLOT(accept()));
817 }
818
819
825 if(p_tableWin->table()->isHidden()) return;
826 if(p_tableWin->table()->item(p_tableWin->currentRow(), 0)->text() == "") return;
827
828 int row = 0;
831 while(p_tableWin->currentRow() >= p_tableWin->table()->rowCount()) {
832
833 row = p_tableWin->table()->rowCount();
834
835 p_tableWin->table()->insertRow(row);
836 for(int c = 0; c < p_tableWin->table()->columnCount(); c++) {
837 QTableWidgetItem *item = new QTableWidgetItem("");
838 p_tableWin->table()->setItem(row, c, item);
839 }
840 }
841
842 QApplication::sendPostedEvents(p_tableWin->table(), 0);
843 p_tableWin->table()->scrollToItem(p_tableWin->table()->item(p_tableWin->currentRow(), 0),
844 QAbstractItemView::PositionAtBottom);
845
846 //Keep track of number times user presses 'R' (record command)
847 p_id = p_tableWin->table()->item(p_tableWin->currentRow() - 1, 0)->text().toInt() + 1;
848 }
849
850
871 updateRow(p);
872 record();
873 }
874
875
881 //Check if the current row is 0
882 if(p_tableWin->currentRow() == 0)
883 p_id = 0;
884 else
885 p_id = p_tableWin->table()->item(p_tableWin->currentRow() - 1, getIndex("ID"))->text().toInt() + 1;
886 }
887
888
895
896 QSettings settings(settingsFilePath() , QSettings::NativeFormat);
897
898 m_showHelpOnStart = settings.value("showHelpOnStart", m_showHelpOnStart).toBool();
899 }
900
901
907
908 QSettings settings(settingsFilePath(), QSettings::NativeFormat);
909
910 settings.setValue("showHelpOnStart", m_showHelpOnStart);
911 }
912
913
920
921 if (QApplication::applicationName() == "") {
922 throw IException(IException::Programmer, "You must set QApplication's "
923 "application name before using the Isis::MainWindow class. Window "
924 "state and geometry can not be saved and restored", _FILEINFO_);
925 }
926
927 FileName config(FileName("$HOME/.Isis/" + QApplication::applicationName() + "/").path() + "/" +
928 "advancedTrackTool.config");
929
930 return config.expanded();
931 }
932}
TableMainWindow * p_tableWin
The table window.
bool eventFilter(QObject *o, QEvent *e)
An event filter that calls methods on certain events.
void readSettings()
Read this tool's preserved state.
int getIndex(QString keyword)
This method finds the index of the header in checkBoxItems by looping through checkBoxItems,...
void addToPermanent(QToolBar *perm)
This method adds the action to bring up the track tool to the permanent tool bar.
void addTo(QMenu *menu)
This method adds the action to bring up the track tool to the menu.
QAction * p_action
Action to bring up the track tool.
void helpDialog()
This method creates a dialog box that shows help tips.
void writeSettings()
Write out this tool's preserved state between runs.
void updateID()
This method updates the record ID.
bool m_showHelpOnStart
True to show dialog When tool is started.
void updateRow(QPoint p)
This method updates the row with data from the point given.
QString settingsFilePath() const
Generate the correct path for the config file.
virtual void mouseMove(QPoint p)
This method is called when the mouse has moved across the viewport and updates the row accordingly.
void record()
This method records data to the current row.
int p_numRows
The number of rows in the table.
virtual void mouseLeave()
This method is called when the mouse leaves the viewport and clears any rows accordingly.
AdvancedTrackTool(QWidget *parent)
Constructs an AdvancedTrackTool object.
void TrackMosaicOrigin(MdiCubeViewport *cvp, int piLine, int piSample, int &piOrigin, QString &psSrcFileName, QString &psSrcSerialNum)
TrackMosaicOrigin - Given the pointer to Cube and line and sample index, finds the origin of the mosa...
Defines an angle and provides unit conversions.
Definition Angle.h:45
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
Distort/undistort focal plane coordinates.
double UndistortedFocalPlaneX() const
Gets the x-value in the undistorted focal plane coordinate system.
Convert between distorted focal plane and detector coordinates.
IO Handler for Isis Cubes.
Definition Cube.h:168
int sampleCount() const
Definition Cube.cpp:1813
PixelType pixelType() const
Definition Cube.cpp:1764
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
Definition Cube.cpp:813
Table readTable(const QString &name)
Read a Table from the cube.
Definition Cube.cpp:958
Distance measurement, usually in meters.
Definition Distance.h:34
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
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Adds specific functionality to C++ strings.
Definition IString.h:165
Cube display widget for certain Isis MDI applications.
bool isLinked() const
Is the viewport linked with other viewports.
Buffer for containing a two dimensional section of an image.
Definition Portal.h:36
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition Projection.h:166
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
Definition Projection.h:166
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:276
Base class for Map Projections of plane shapes.
double UniversalRingRadius()
This returns a universal radius, which is just the radius in meters.
static double To180Domain(const double lon)
This method converts a ring longitude into the -180 to 180 domain.
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
Base class for Map TProjections.
static double To180Domain(const double lon)
This method converts a longitude into the -180 to 180 domain.
virtual double UniversalLatitude()
This returns a universal latitude (planetocentric).
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
Class for storing Table blobs information.
Definition Table.h:61
int Records() const
Returns the number of records.
Definition Table.cpp:313
a subclass of the qisis mainwindow, tablemainwindow handles all of the table tasks.
QTableWidget * table() const
Returns the table.
void showTable()
This method checks to see if the table has been created.
void addToTable(bool setOn, const QString &heading, const QString &menuText="", int insertAt=-1, Qt::Orientation o=Qt::Horizontal, QString toolTip="")
Adds a new column to the table when a new curve is added to the plot.
void setCurrentRow(int row)
Sets the current row to row.
int currentRow() const
Returns the current row.
int currentIndex() const
Returns the current index.
void setTrackListItems(bool track=false)
If this property is true, the class will keep track of the checked/unchecked items in the dock area w...
void clearRow(int row)
This method clears the text of the given row.
void setCurrentIndex(int currentIndex)
Sets the current index to currentIndex.
void setStatusMessage(QString message)
sets the status message in the lower lefthand corner of the window.
Base class for the Qisis tools.
Definition Tool.h:67
void activate(bool)
Activates the tool.
Definition Tool.cpp:131
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
Table to store tracking information for a mosaic.
Parse and return pieces of a time string.
Definition iTime.h:65
double Et() const
Returns the ephemeris time (TDB) representation of the time as a double.
Definition iTime.h:126
QString UTC(int precision=8) const
Returns the internally stored time, formatted as a UTC time.
Definition iTime.cpp:405
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
int SizeOf(Isis::PixelType pixelType)
Returns the number of bytes of the specified PixelType.
Definition PixelType.h:46
bool IsValidPixel(const double d)
Returns if the input pixel is valid.
const double Null
Value for an Isis Null pixel.
QString PixelToString(double d, double precision=8)
Takes a double pixel value and returns the name of the pixel type as a string.