Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Isis 3 Programmer Reference
CubeViewport.cpp
1
6
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "CubeViewport.h"
10
11#include <iomanip>
12#include <iostream>
13#include <QApplication>
14#include <QClipboard>
15#include <QCloseEvent>
16#include <QCursor>
17#include <QDebug>
18#include <QIcon>
19#include <QPen>
20#include <QPainter>
21#include <QFileInfo>
22#include <QMessageBox>
23#include <QMouseEvent>
24#include <QRgb>
25#include <QScrollBar>
26#include <QString>
27#include <QTimer>
28
29#include "Brick.h"
30#include "Camera.h"
31#include "CubeDataThread.h"
32#include "IException.h"
33#include "IString.h"
34#include "FileName.h"
35#include "Histogram.h"
36#include "Pvl.h"
37#include "PvlGroup.h"
38#include "PvlKeyword.h"
39#include "PvlObject.h"
40#include "Stretch.h"
41#include "CubeStretch.h"
42#include "StretchTool.h"
43#include "Tool.h"
44#include "UniversalGroundMap.h"
45#include "ViewportBuffer.h"
46
47
48using namespace std;
49
50
51namespace Isis {
60 QWidget *parent) : QAbstractScrollArea(parent) {
61 // Is the cube usable?
62 if(cube == NULL) {
63 throw IException(IException::Programmer,
64 "Can not view NULL cube pointer",
65 _FILEINFO_);
66 }
67 else if(!cube->isOpen()) {
68 throw IException(IException::Programmer,
69 "Can not view unopened cube",
70 _FILEINFO_);
71 }
72
73 p_cube = cube;
74 p_cubeData = NULL;
75
76 if (cubeData)
77 {
78 p_cubeData = cubeData;
79 p_thisOwnsCubeData = false;
80 p_cubeId = p_cubeData->FindCubeId(cube);
81 }
82 else
83 {
85 p_thisOwnsCubeData = true;
86 p_cubeId = p_cubeData->AddCube(p_cube);
87 }
88
89 if(p_cube->hasGroup("Tracking")) {
90 setTrackingCube();
91 }
92 else {
93 p_trackingCube = NULL;
94 }
95
96
97 connect(p_cubeData, SIGNAL(BrickChanged(int, const Isis::Brick *)),
98 this, SLOT(cubeDataChanged(int, const Isis::Brick *)));
99 connect(this, SIGNAL(doneWithData(int, const Isis::Brick *)),
100 p_cubeData, SLOT(DoneWithData(int, const Isis::Brick *)));
101
102 p_cubeData->AddChangeListener();
103
104 void doneWithData(int, const Brick *);
105
106 // Set up the scroll area
107 setAttribute(Qt::WA_DeleteOnClose);
108 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
109 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
110 viewport()->setObjectName("viewport");
111 viewport()->setCursor(QCursor(Qt::CrossCursor));
112 viewport()->installEventFilter(this);
113 viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
114
115 setAttribute(Qt::WA_NoSystemBackground);
116 setFrameShadow(QFrame::Plain);
117 setFrameShape(QFrame::NoFrame);
118 setAutoFillBackground(false);
119
120// viewport()->setAttribute(Qt::WA_NoSystemBackground);
121// viewport()->setAttribute(Qt::WA_PaintOnScreen,false);
122
123 p_saveEnabled = false;
124 // Save off info about the cube
125 p_scale = -1.0;
126 p_color = false;
127
128
129 setCaption();
130
131 p_redBrick = new Brick(4, 1, 1, cube->pixelType());
132 p_grnBrick = new Brick(4, 1, 1, cube->pixelType());
133 p_bluBrick = new Brick(4, 1, 1, cube->pixelType());
134 p_gryBrick = new Brick(4, 1, 1, cube->pixelType());
135 p_pntBrick = new Brick(4, 1, 1, cube->pixelType());
136
137 p_paintPixmap = false;
138 p_image = NULL;
139 p_cubeShown = true;
140 p_updatingBuffers = false;
141
142 //updateScrollBars(1,1);
143
144 p_groundMap = NULL;
145 p_projection = NULL;
146 p_camera = NULL;
147
148 // Setup a universal ground map
149 try {
151 }
152 catch(IException &) {
153 }
154
155 if(p_groundMap != NULL) {
156 // Setup the camera or the projection
157 if(p_groundMap->Camera() != NULL) {
158 p_camera = p_groundMap->Camera();
159 if(p_camera->HasProjection()) {
160 try {
161 p_projection = cube->projection();
162 }
163 catch(IException &) {
164 }
165 }
166 }
167 else {
168 p_projection = p_groundMap->Projection();
169 }
170 }
171
172
173 // Setup context sensitive help
174 QString cubeFileName = p_cube->fileName();
175 p_whatsThisText = QString("<b>Function: </b>Viewport to ") + cubeFileName;
176
178 "<p><b>Cube Dimensions:</b> \
179 <blockQuote>Samples = " +
180 QString::number(cube->sampleCount()) + "<br>" +
181 "Lines = " +
182 QString::number(cube->lineCount()) + "<br>" +
183 "Bands = " +
184 QString::number(cube->bandCount()) + "</blockquote></p>";
185
186 /*setting up the qlist of CubeBandsStretch objs.
187 for( int b = 0; b < p_cube->bandCount(); b++) {
188 CubeBandsStretch *stretch = new CubeBandsStretch();
189 p_bandsStretchList.push_back(stretch);
190 }*/
191
193 p_grayBuffer->enable(false);
194 p_grayBuffer->setBand(1);
195
196 p_redBuffer = NULL;
197 p_greenBuffer = NULL;
198 p_blueBuffer = NULL;
199 p_pixmapPaintRects = NULL;
200
202 p_progressTimer = new QTimer();
203 p_progressTimer->setInterval(250);
204
207
208 while(p_cube->bandCount() > p_knownStretches->size()) {
209 p_knownStretches->push_back(NULL);
210 p_globalStretches->push_back(NULL);
211 }
212
213 connect(p_progressTimer, SIGNAL(timeout()), this, SLOT(onProgressTimer()));
214
215 p_bgColor = Qt::black;
216
217 p_comboCount = 0;
218 p_comboIndex = 0;
219
220 p_image = new QImage(viewport()->size(), QImage::Format_RGB32);
221 }
222
223
232 void CubeViewport::showEvent(QShowEvent *event) {
233 if(p_scale == -1) {
234 // This doesn't equal fitScale() ... causes misalignment in qview initial
235 // view versus zoomFit
236 //double sampScale = (double) sizeHint().width() / (double) cubeSamples();
237 //double lineScale = (double) sizeHint().height() / (double) cubeLines();
238 //double scale = sampScale < lineScale ? sampScale : lineScale;
239
240 setScale(fitScale(), cubeSamples() / 2.0 + 0.5, cubeLines() / 2.0 + 0.5);
241 }
242
243 if(p_grayBuffer && !p_grayBuffer->enabled()) {
244 p_grayBuffer->enable(true);
245
246 // gives a proper initial stretch (entire cube)
247 p_grayBuffer->addStretchAction();
248 }
249
250 QAbstractScrollArea::show();
251
252 p_paintPixmap = true;
253
254 paintPixmap();
255 }
256
257
263 double progress = 0.0;
264 bool completed = false;
265
266 if(p_grayBuffer) {
267 progress += p_grayBuffer->currentProgress();
268 completed = !p_grayBuffer->working();
269 }
270
271 if(p_redBuffer) {
272 progress += p_redBuffer->currentProgress() / 3.0;
273 completed = !p_redBuffer->working();
274 }
275
276 if(p_greenBuffer) {
277 progress += p_greenBuffer->currentProgress() / 3.0;
278 completed = completed && !p_greenBuffer->working();
279 }
280
281 if(p_blueBuffer) {
282 progress += p_blueBuffer->currentProgress() / 3.0;
283 completed = completed && !p_blueBuffer->working();
284 }
285
286 int realProgress = (int)(progress * 100.0);
287
288 if(completed) {
289 realProgress = 100;
290 p_progressTimer->stop();
291 emit progressComplete();
292 emit screenPixelsChanged();
293 }
294 else if(realProgress == 100) {
295 realProgress = 99;
296 }
297
298 emit progressChanged(realProgress);
299 }
300
301
307 if(p_redBrick) {
308 delete p_redBrick;
309 p_redBrick = NULL;
310 }
311
312 if(p_grnBrick) {
313 delete p_grnBrick;
314 p_grnBrick = NULL;
315 }
316
317 if(p_bluBrick) {
318 delete p_bluBrick;
319 p_bluBrick = NULL;
320 }
321
322 if(p_gryBrick) {
323 delete p_gryBrick;
324 p_gryBrick = NULL;
325 }
326
327 if(p_pntBrick) {
328 delete p_pntBrick;
329 p_pntBrick = NULL;
330 }
331
332 if(p_groundMap) {
333 delete p_groundMap;
334 p_groundMap = NULL;
335 }
336
337 if(p_grayBuffer) {
338 delete p_grayBuffer;
339 p_grayBuffer = NULL;
340 }
341
342 if(p_redBuffer) {
343 delete p_redBuffer;
344 p_redBuffer = NULL;
345 }
346
347 if(p_greenBuffer) {
348 delete p_greenBuffer;
349 p_greenBuffer = NULL;
350 }
351
352 if(p_blueBuffer) {
353 delete p_blueBuffer;
354 p_blueBuffer = NULL;
355 }
356
357 // p_cubeData MUST be deleted AFTER all viewport buffers!!!
358 if(p_cubeData) {
359 p_cubeData->RemoveChangeListener();
360
362 delete p_cubeData;
363
364 p_cubeData = NULL;
365 }
366
367 p_cube = NULL;
368
369 delete p_trackingCube;
370 p_trackingCube = NULL;
371
372 if(p_progressTimer) {
373 delete p_progressTimer;
374 p_progressTimer = NULL;
375 }
376
377 if(p_image) {
378 delete p_image;
379 p_image = NULL;
380 }
381
383 for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) {
384 delete(*p_pixmapPaintRects)[rect];
385 }
386
387 delete p_pixmapPaintRects;
388 p_pixmapPaintRects = NULL;
389 }
390
391 if(p_knownStretches) {
392 for(int stretch = 0; stretch < p_knownStretches->size(); stretch ++) {
393 if((*p_knownStretches)[stretch] != NULL) {
394 delete(*p_knownStretches)[stretch];
395 (*p_knownStretches)[stretch] = NULL;
396 }
397 }
398
399 p_knownStretches->clear();
400
401 delete p_knownStretches;
402 p_knownStretches = NULL;
403 }
404
406 for(int stretch = 0; stretch < p_globalStretches->size(); stretch ++) {
407 if((*p_globalStretches)[stretch] != NULL) {
408 delete(*p_globalStretches)[stretch];
409 (*p_globalStretches)[stretch] = NULL;
410 }
411 }
412
413 p_globalStretches->clear();
414
415 delete p_globalStretches;
416 p_globalStretches = NULL;
417 }
418 }
419
426 p_cube = cube;
427 setCaption();
428 }
429
430
433 return p_cube->sampleCount();
434 }
435
436
439 return p_cube->lineCount();
440 }
441
442
445 return p_cube->bandCount();
446 }
447
448
456 void CubeViewport::cubeDataChanged(int cubeId, const Brick *data) {
457 if(cubeId == p_cubeId) {
458 double ss, sl, es, el;
459 ss = data->Sample();
460 sl = data->Line();
461 es = data->Sample() + data->SampleDimension();
462 el = data->Line() + data->LineDimension();
463 if(ss < 0.5){
464 ss = 0.5;
465 }
466 if(sl < 0.5){
467 sl = 0.5;
468 }
469 if(es > cube()->sampleCount() + 0.5){
470 es = cube()->sampleCount() + 0.5;
471 }
472 if(el > cube()->lineCount() + 0.5){
473 el = cube()->lineCount() + 0.5;
474 }
475
476 int sx, sy, ex, ey;
477
478 cubeToViewport(ss, sl, sx, sy);
479 cubeToViewport(es, el, ex, ey);
480 if(sx < 0){
481 sx = 0;
482 }
483 if(sy < 0){
484 sy = 0;
485 }
486 if(ex > viewport()->width()){
487 ex = viewport()->width();
488 }
489 if(ey > viewport()->height()){
490 ey = viewport()->height();
491 }
492 QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1);
493
494 p_updatingBuffers = true;
495 if(p_grayBuffer){
496 p_grayBuffer->fillBuffer(vpRect, data);
497 }
498 if(p_redBuffer){
499 p_redBuffer->fillBuffer(vpRect, data);
500 }
501 if(p_greenBuffer){
502 p_greenBuffer->fillBuffer(vpRect, data);
503 }
504 if(p_blueBuffer){
505 p_blueBuffer->fillBuffer(vpRect, data);
506 }
507 p_updatingBuffers = false;
508
510 }
511
512 emit doneWithData(cubeId, data);
513 }
514
515
525 bool canClose = true;
526 if(p_saveEnabled) {
527 // Enter == button 0, Escape == button 2
528 switch(QMessageBox::information(this, tr("Confirm Save"),
529 tr("The cube [<font color='red'>%1</font>] contains unsaved changes. "
530 "Do you want to save the changes before exiting?").arg(cube()->fileName()),
531 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) {
532 //Save changes and close viewport
533 case QMessageBox::Save:
534 emit saveChanges(this);
535 break;
536
537 //Discard changes and close viewport
538 case QMessageBox::Discard:
539 emit discardChanges(this);
540 break;
541
542 //Cancel, don't close viewport
543 case QMessageBox::Cancel:
544 default:
545 canClose = false;
546 break;
547 }
548 }
549
550// if (canClose) emit viewportClosed(this);
551 return canClose;
552 }
553
560 void CubeViewport::cubeChanged(bool changed) {
561 p_saveEnabled = changed;
562 }
563
571 QSize s(512, 512);
572 return s;
573 }
574
575
588 // Sanitize the scale value
589 if (scale == p_scale){
590 return;
591 }
592
593 if (viewport()->width() && viewport()->height()) {
594 // don't let zoom scale be larger than the viewport size
595 double maxScale = max(viewport()->width(),viewport()->height());
596 if (scale > maxScale) {
597 scale = maxScale;
598 }
599 // don't let zoom scale be smaller than one pixel high/wide showing
600 double minScale = 1.0 / (min(cubeSamples(),cubeLines()));
601 if (scale < minScale) {
602 scale = minScale;
603 }
604 }
605
606 // Resize the scrollbars to reflect the new scale
607 double samp, line;
608 contentsToCube(horizontalScrollBar()->value(), verticalScrollBar()->value(),
609 samp, line);
610 p_scale = scale;
611 updateScrollBars(1, 1); // Setting to 1,1 make sure we don't have bad values
612
613 // Now update the scroll bar value to the old line/sample
614 int x, y;
615 cubeToContents(samp, line, x, y);
616 updateScrollBars(x, y);
617
618 p_updatingBuffers = true;
619 if (p_grayBuffer){
620 p_grayBuffer->scaleChanged();
621 }
622 if (p_redBuffer){
623 p_redBuffer->scaleChanged();
624 }
625 if (p_greenBuffer){
626 p_greenBuffer->scaleChanged();
627 }
628 if (p_blueBuffer){
629 p_blueBuffer->scaleChanged();
630 }
631 p_updatingBuffers = false;
632
634
635 // Notify other tools about the scale change
636 emit scaleChanged();
637
638 // Update the display
639 setCaption();
640 paintPixmap(); // Will get rid of old data in the display
641
642 viewport()->repaint();
643 emit screenPixelsChanged();
644 }
645
654 void CubeViewport::setScale(double scale, int x, int y) {
655 double samp, line;
656 viewportToCube(x, y, samp, line);
657 setScale(scale, samp, line);
658 }
659
660
670 void CubeViewport::setScale(double scale, double sample, double line) {
671 viewport()->setUpdatesEnabled(false);
672
673 bool wasEnabled = false;
674
675 if ((p_grayBuffer && p_grayBuffer->enabled()) ||
676 (p_redBuffer && p_redBuffer->enabled())) {
677 wasEnabled = true;
678 }
679
680 if (p_grayBuffer){
681 p_grayBuffer->enable(false);
682 }
683 if (p_redBuffer){
684 p_redBuffer->enable(false);
685 }
686 if (p_greenBuffer){
687 p_greenBuffer->enable(false);
688 }
689 if (p_blueBuffer){
690 p_blueBuffer->enable(false);
691 }
692 if (p_paintPixmap) {
693 p_paintPixmap = false;
695 p_paintPixmap = true;
696 }
697 else {
699 }
700 center(sample, line);
701
702 if (p_grayBuffer){
703 p_grayBuffer->enable(wasEnabled);
704 }
705 if (p_redBuffer){
706 p_redBuffer->enable(wasEnabled);
707 }
708 if (p_greenBuffer){
709 p_greenBuffer->enable(wasEnabled);
710 }
711 if (p_blueBuffer){
712 p_blueBuffer->enable(wasEnabled);
713 }
714
715 paintPixmap();
716 viewport()->setUpdatesEnabled(true);
717 viewport()->update();
718 emit screenPixelsChanged();
719 }
720
721
729 void CubeViewport::center(int x, int y) {
730 double sample, line;
731 viewportToCube(x, y, sample, line);
732 center(sample, line);
733 }
734
735
742 void CubeViewport::center(double sample, double line) {
743 int x, y;
744 cubeToContents(sample, line, x, y);
745
746 int panX = horizontalScrollBar()->value() - x;
747 int panY = verticalScrollBar()->value() - y;
748
749 updateScrollBars(x, y);
750
751 p_updatingBuffers = true;
752 if(p_grayBuffer){
753 p_grayBuffer->pan(panX, panY);
754 }
755 if(p_redBuffer){
756 p_redBuffer->pan(panX, panY);
757 }
758 if(p_greenBuffer){
759 p_greenBuffer->pan(panX, panY);
760 }
761 if(p_blueBuffer){
762 p_blueBuffer->pan(panX, panY);
763 }
764 p_updatingBuffers = false;
765
767
768 shiftPixmap(panX, panY);
769
770 emit screenPixelsChanged();
771 }
772
773
779 for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) {
781 }
782
783 p_pixmapPaintRects->clear();
784 }
785
786
798 double &sample, double &line) const {
799 sample = x / p_scale;
800 line = y / p_scale;
801 }
802
803
815 double &sample, double &line) const {
816 x += horizontalScrollBar()->value();
817 x -= viewport()->width() / 2;
818 y += verticalScrollBar()->value();
819 y -= viewport()->height() / 2;
820 contentsToCube(x, y, sample, line);
821 }
822
823
834 void CubeViewport::cubeToContents(double sample, double line,
835 int &x, int &y) const {
836 x = (int)(sample * p_scale + 0.5);
837 y = (int)(line * p_scale + 0.5);
838 }
839
840
851 void CubeViewport::cubeToViewport(double sample, double line,
852 int &x, int &y) const {
853 cubeToContents(sample, line, x, y);
854 x -= horizontalScrollBar()->value();
855 x += viewport()->width() / 2;
856 y -= verticalScrollBar()->value();
857 y += viewport()->height() / 2;
858 }
859
860
868 void CubeViewport::scrollBy(int dx, int dy) {
869 // Make sure we don't generate bad values outside of the scroll range
870 int x = horizontalScrollBar()->value() + dx;
871 if(x <= 1) {
872 dx = 1 - horizontalScrollBar()->value();
873 }
874 else if(x >= horizontalScrollBar()->maximum()) {
875 dx = horizontalScrollBar()->maximum() - horizontalScrollBar()->value();
876 }
877
878 // Make sure we don't generate bad values outside of the scroll range
879 int y = verticalScrollBar()->value() + dy;
880 if(y <= 1) {
881 dy = 1 - verticalScrollBar()->value();
882 }
883 else if(y >= verticalScrollBar()->maximum()) {
884 dy = verticalScrollBar()->maximum() - verticalScrollBar()->value();
885 }
886
887 // Do we do anything?
888 if((dx == 0) && (dy == 0)){
889 return;
890 }
891
892 // We do so update the scroll bars
893 updateScrollBars(horizontalScrollBar()->value() + dx,
894 verticalScrollBar()->value() + dy);
895
896 // Scroll the the pixmap
897 scrollContentsBy(-dx, -dy);
898 }
899
900
908 void CubeViewport::scrollContentsBy(int dx, int dy) {
909
910 // We shouldn't do anything if scrollbars are being updated
911 if(viewport()->signalsBlocked()) {
912 return;
913 }
914
915 // Tell the buffers to update appropriate for the pan and upon completion
916 // they will call bufferUpdated. We don't want bufferUpdated to happen
917 // until afterwards. If only shrinking and no new data then the viewport
918 // buffers will complete immediately. When all buffers don't have their
919 // appropriate actions queued bufferUpdated can't succeed.
920
921 // Also block paints because we'll repaint it all when we're done
922 // telling each buffer about the pan.
923 bool panQueued = false;
924 QRect bufferXYRect;
925
926 p_updatingBuffers = true;
927
928 if(p_grayBuffer) {
929 p_grayBuffer->pan(dx, dy);
930 panQueued |= p_grayBuffer->working();
931 bufferXYRect = p_grayBuffer->bufferXYRect();
932 }
933
934 if(p_redBuffer) {
935 p_redBuffer->pan(dx, dy);
936 panQueued |= p_redBuffer->working();
937 bufferXYRect = p_redBuffer->bufferXYRect();
938 }
939
940 if(p_greenBuffer) {
941 p_greenBuffer->pan(dx, dy);
942 panQueued |= p_greenBuffer->working();
943 }
944
945 if(p_blueBuffer) {
946 p_blueBuffer->pan(dx, dy);
947 panQueued |= p_blueBuffer->working();
948 }
949
950 p_updatingBuffers = false;
951
952 // shift the pixmap by x,y if the viewport buffer didn't do it immediately
953 if(panQueued) {
954 shiftPixmap(dx, dy);
955 }
956 else {
957 // Need to do this to clear area outside of cube
958 p_pixmapPaintRects->clear();
959 paintPixmap();
960 }
961
962 viewport()->update();
963 emit screenPixelsChanged();
964 }
965
966
972 if(!p_progressTimer->isActive()) {
973 p_progressTimer->start();
974
975 emit progressChanged(0);
976 }
977 }
978
979
985 QString cubeFileName = p_cube->fileName();
986 QString str = QFileInfo(cubeFileName).fileName();
987 str += QString(" @ ");
988 str += QString::number(p_scale * 100.0);
989 str += QString("% ");
990
991 if(p_color) {
992 str += QString("(RGB = ");
993 str += QString::number(p_red.band);
994 str += QString(",");
995 str += QString::number(p_green.band);
996 str += QString(",");
997 str += QString::number(p_blue.band);
998 str += QString(")");
999 }
1000 else {
1001 str += QString("(Gray = ");
1002 str += QString::number(p_gray.band);
1003 str += QString(")");
1004 }
1005
1006 //If changes have been made make sure to add '*' to the end
1007 if(p_saveEnabled) {
1008 str += "*";
1009 }
1010
1011 parentWidget()->setWindowTitle(str);
1012 emit windowTitleChanged();
1013 }
1014
1015
1022 void CubeViewport::resizeEvent(QResizeEvent *e) {
1023 p_paintPixmap = false;
1024
1025 // Tell the buffers to update their coefficients to reinitialize
1026 // and have their immediate paint events happen afterwards. Should not
1027 // happen, but if buffers have actions complete immediately and call
1028 // bufferUpdated. We don't want to have bufferUpdated ever when all
1029 // buffers don't have their appropriate actions queued. It can't succeed.
1030 p_updatingBuffers = true;
1031 if(p_grayBuffer){
1032 p_grayBuffer->resizedViewport();
1033 }
1034 if(p_redBuffer){
1035 p_redBuffer->resizedViewport();
1036 }
1037 if(p_greenBuffer){
1038 p_greenBuffer->resizedViewport();
1039 }
1040 if(p_blueBuffer){
1041 p_blueBuffer->resizedViewport();
1042 }
1043 p_updatingBuffers = false;
1044
1046
1047 // Change the size of the image and pixmap
1048 if(p_image) {
1049 delete p_image;
1050 p_image = NULL;
1051 }
1052
1053 p_image = new QImage(viewport()->size(), QImage::Format_RGB32);
1054 p_pixmap = QPixmap(viewport()->size());
1055
1056 p_paintPixmap = true;
1057
1058 // Fixup the scroll bars
1059 updateScrollBars(horizontalScrollBar()->value(),
1060 verticalScrollBar()->value());
1061
1063 "<p><b>Viewport Dimensions:</b> \
1064 <blockQuote>Samples = " +
1065 QString::number(viewport()->width()) + "<br>" +
1066 "Lines = " +
1067 QString::number(viewport()->height()) + "</blockquote></p>";
1068
1069 // Repaint the pixmap
1070 paintPixmap();
1071
1072 // Repaint the internal viewport and scroll bars
1073 viewport()->update();
1074 emit screenPixelsChanged();
1075 }
1076
1077
1088 void CubeViewport::paintEvent(QPaintEvent *e) {
1089 if(!p_cubeShown || !viewport()->isVisible()){
1090 return;
1091 }
1092 }
1093
1094
1104 paintPixmap(rect);
1105
1106 // Don't repaint from buffer updates if any buffers are working...
1107 // This set of statements fixes a flash of black when in RGB mode
1108 // and a pan (or other operation?) completes. What would happen is
1109 // the first would reset to black then other buffers still working so
1110 // not restored to DN values.
1111 if(p_grayBuffer && p_grayBuffer->working()){
1112 return;
1113 }
1114 if(p_redBuffer && p_redBuffer->working()){
1115 return;
1116 }
1117 if(p_greenBuffer && p_greenBuffer->working()){
1118 return;
1119 }
1120 if(p_blueBuffer && p_blueBuffer->working()){
1121 return;
1122 }
1123
1124 viewport()->repaint(rect);
1125 }
1126
1129 QRect rect(0, 0, p_image->width(), p_image->height());
1130 paintPixmap(rect);
1131 }
1132
1133
1140 void CubeViewport::paintPixmap(QRect rect) {
1141 if(!p_paintPixmap) {
1142 return;
1143 }
1144
1145 if(p_updatingBuffers) {
1146 p_pixmapPaintRects->push_back(new QRect(rect));
1147 return;
1148 }
1149
1150 if(p_pixmap.isNull()){
1151 return;
1152 }
1153
1154 QPainter p(&p_pixmap);
1155
1156 p.fillRect(rect, QBrush(p_bgColor));
1157
1158 QRect dataArea;
1159
1160 if(p_grayBuffer && p_grayBuffer->enabled()) {
1161 if(p_grayBuffer->working()){
1162 return;
1163 }
1164
1165 dataArea = QRect(p_grayBuffer->bufferXYRect().intersected(rect));
1166
1167 for(int y = dataArea.top();
1168 !dataArea.isNull() && y <= dataArea.bottom();
1169 y++) {
1170 const vector< double > & line =
1171 p_grayBuffer->getLine(y - p_grayBuffer->bufferXYRect().top());
1172
1173 if(line.size() == 0) {
1174 break;
1175 }
1176
1177 if(y >= p_image->height()) {
1178 throw IException(IException::Programmer, "y too big", _FILEINFO_);
1179 }
1180
1181 QRgb *rgb = (QRgb *) p_image->scanLine(y);
1182
1183 CubeStretch redStretch = p_red.getStretch();
1184 CubeStretch greenStretch = p_green.getStretch();
1185 CubeStretch blueStretch = p_blue.getStretch();
1186
1187 for(int x = dataArea.left(); x <= dataArea.right(); x++) {
1188 int bufferLeft = p_grayBuffer->bufferXYRect().left();
1189 int bufferX = x - bufferLeft;
1190
1191 if(bufferX >= (int)line.size()){
1192 break;
1193 }
1194
1195 if(bufferX < 0) {
1196 throw IException(IException::Programmer, "bufferX < 0", _FILEINFO_);
1197 }
1198
1199 if(x >= p_image->width()) {
1200 throw IException(IException::Programmer, "x too big", _FILEINFO_);
1201 }
1202
1203 double bufferVal = line.at(bufferX);
1204
1205 // This is still RGB; the pairs are identical but the boundary
1206 // conditions are different. Display saturations cause this.
1207 int redPix = (int)(redStretch.Map(bufferVal) + 0.5);
1208 int greenPix = (int)(greenStretch.Map(bufferVal) + 0.5);
1209 int bluePix = (int)(blueStretch.Map(bufferVal) + 0.5);
1210 rgb[x] = qRgb(redPix, greenPix, bluePix);
1211 }
1212 }
1213 }
1214 else {
1215 if(p_redBuffer && p_redBuffer->enabled()) {
1216 if(p_redBuffer->working() || p_greenBuffer->working() ||
1217 p_blueBuffer->working()) {
1218 return;
1219 }
1220
1221
1222 if((p_greenBuffer->bufferXYRect().top() !=
1223 p_redBuffer->bufferXYRect().top()) ||
1224 (p_greenBuffer->bufferXYRect().top() !=
1225 p_blueBuffer->bufferXYRect().top())) {
1226 throw IException(IException::Programmer,
1227 "Buffer rects mismatched",
1228 _FILEINFO_);
1229 }
1230
1231 if((p_greenBuffer->bufferXYRect().left() !=
1232 p_redBuffer->bufferXYRect().left()) ||
1233 (p_greenBuffer->bufferXYRect().left() !=
1234 p_blueBuffer->bufferXYRect().left())) {
1235 throw IException(IException::Programmer,
1236 "Buffer rects mismatched",
1237 _FILEINFO_);
1238 }
1239
1240 dataArea = QRect(p_redBuffer->bufferXYRect().intersected(rect));
1241
1242 for(int y = dataArea.top();
1243 !dataArea.isNull() && y <= dataArea.bottom();
1244 y++) {
1245 int bufferLine = y - p_redBuffer->bufferXYRect().top();
1246
1247 const vector<double> &redLine = p_redBuffer->getLine(bufferLine);
1248 const vector<double> &greenLine = p_greenBuffer->getLine(bufferLine);
1249 const vector<double> &blueLine = p_blueBuffer->getLine(bufferLine);
1250
1251 if((int)redLine.size() < dataArea.width() ||
1252 (int)greenLine.size() < dataArea.width() ||
1253 (int)blueLine.size() < dataArea.width()) {
1254 throw IException(IException::Programmer,
1255 "Empty buffer line",
1256 _FILEINFO_);
1257 }
1258
1259 QRgb *rgb = (QRgb *) p_image->scanLine(y);
1260
1261 CubeStretch redStretch = p_red.getStretch();
1262 CubeStretch greenStretch = p_green.getStretch();
1263 CubeStretch blueStretch = p_blue.getStretch();
1264
1265 for(int x = dataArea.left(); x <= dataArea.right(); x++) {
1266 int redPix = (int)(redStretch.Map(redLine[ x - p_redBuffer->bufferXYRect().left()]) + 0.5);
1267 int greenPix = (int)(greenStretch.Map(greenLine[ x - p_greenBuffer->bufferXYRect().left()]) + 0.5);
1268 int bluePix = (int)(blueStretch.Map(blueLine[ x - p_blueBuffer->bufferXYRect().left()]) + 0.5);
1269
1270 rgb[x] = qRgb(redPix, greenPix, bluePix);
1271 }
1272 }
1273 }
1274 }
1275
1276 if(!dataArea.isNull()){
1277 p.drawImage(dataArea.topLeft(), *p_image, dataArea);
1278 }
1279
1280 // Change whats this info
1282 }
1283
1284
1291 void CubeViewport::shiftPixmap(int dx, int dy) {
1292 if(!p_paintPixmap || !p_pixmap){
1293 return;
1294 }
1295
1296 // Prep to scroll the pixmap
1297 int drawStartX = dx;
1298 int pixmapStartX = 0;
1299 if(drawStartX < 0) {
1300 drawStartX = 0;
1301 pixmapStartX = -dx;
1302 }
1303
1304 int drawStartY = dy;
1305 int pixmapStartY = 0;
1306 if(dy < 0) {
1307 drawStartY = 0;
1308 pixmapStartY = -dy;
1309 }
1310
1311 // Ok we can shift the pixmap and filling
1312 int pixmapDrawWidth = p_pixmap.width() - pixmapStartX + 1;
1313 int pixmapDrawHeight = p_pixmap.height() - pixmapStartY + 1;
1314
1315 QRect rect(0, 0, p_pixmap.width(), p_pixmap.height());
1316 QPixmap pixmapCopy = p_pixmap.copy();
1317
1318 QPainter painter(&p_pixmap);
1319 painter.fillRect(rect, QBrush(p_bgColor));
1320 painter.drawPixmap(drawStartX, drawStartY,
1321 pixmapCopy,
1322 pixmapStartX, pixmapStartY,
1323 pixmapDrawWidth, pixmapDrawHeight);
1324 painter.end();
1325
1326 // Now fill in the left or right side
1327 QRect xFillRect;
1328 QRect yFillRect;
1329
1330 if(dx > 0) {
1331 xFillRect = QRect(QPoint(0, 0),
1332 QPoint(dx, p_pixmap.height()));
1333 }
1334 else {
1335 if(dx < 0){
1336 xFillRect = QRect(QPoint(p_pixmap.width() + dx, 0),
1337 QPoint(p_pixmap.width(), p_pixmap.height()));
1338 }
1339 }
1340
1341 // Fill in the top or bottom side
1342 if(dy > 0) {
1343 yFillRect = QRect(QPoint(0, 0),
1344 QPoint(p_pixmap.width(), dy));
1345 }
1346 else {
1347 if(dy < 0){
1348 yFillRect = QRect(QPoint(0, p_pixmap.height() + dy),
1349 QPoint(p_pixmap.width(), p_pixmap.height()));
1350 }
1351 }
1352
1353 if(dx != 0) {
1354 paintPixmap(xFillRect);
1355 }
1356
1357 if(dy != 0) {
1358 paintPixmap(yFillRect);
1359 }
1360
1361 viewport()->update();
1362 }
1363
1371 void CubeViewport::getAllWhatsThisInfo(Pvl & pWhatsThisPvl)
1372 {
1373 // Get Cube Info
1374 PvlObject whatsThisObj = PvlObject("WhatsThis");
1375 whatsThisObj += PvlKeyword("Cube", p_cube->fileName());
1376
1377 PvlGroup cubeGrp("CubeDimensions");
1378 cubeGrp += PvlKeyword("Samples", toString(p_cube->sampleCount()));
1379 cubeGrp += PvlKeyword("Lines", toString(p_cube->lineCount()));
1380 cubeGrp += PvlKeyword("Bands", toString(p_cube->bandCount()));
1381 whatsThisObj += cubeGrp;
1382
1383 // Get Viewport Info
1384 PvlGroup viewportGrp("ViewportDimensions");
1385 viewportGrp += PvlKeyword("Samples", toString(viewport()->width()));
1386 viewportGrp += PvlKeyword("Lines", toString(viewport()->height()));
1387 whatsThisObj += viewportGrp;
1388
1389 // Get Cube area Info
1390 PvlObject cubeAreaPvl("CubeArea");
1391 PvlGroup bandGrp("Bands");
1392
1393 PvlKeyword filterName;
1394 getBandFilterName(filterName);
1395 int iFilterSize = filterName.size();
1396
1397 // color
1398 if(p_color ) {
1399 PvlKeyword virtualKey("Virtual"), physicalKey("Physical"), filterNameKey;
1400 int iRedBand = p_redBuffer->getBand();
1401 int iGreenBand = p_greenBuffer->getBand();
1402 int iBlueBand = p_blueBuffer->getBand();
1403
1404 bandGrp += PvlKeyword("Color", "RGB");
1405
1406 virtualKey = toString(iRedBand);
1407 virtualKey += toString(iGreenBand);
1408 virtualKey += toString(iBlueBand);
1409 bandGrp += virtualKey;
1410
1411 physicalKey = toString(p_cube->physicalBand(iRedBand));
1412 physicalKey += toString(p_cube->physicalBand(iGreenBand));
1413 physicalKey += toString(p_cube->physicalBand(iBlueBand));
1414 bandGrp += physicalKey;
1415
1416 if(iFilterSize) {
1417 if(iRedBand <= iFilterSize) {
1418 filterNameKey += filterName[iRedBand-1];
1419 }
1420 else {
1421 filterNameKey += "None";
1422 }
1423
1424 if(iGreenBand <= iFilterSize) {
1425 filterNameKey += filterName[iGreenBand-1];
1426 }
1427 else {
1428 filterNameKey += "None";
1429 }
1430
1431 if(iBlueBand <= iFilterSize) {
1432 filterNameKey += filterName[iBlueBand-1];
1433 }
1434 else {
1435 filterNameKey += "None";
1436 }
1437 bandGrp += filterNameKey;
1438 }
1439 }
1440 else { // gray
1441 int iGrayBand = p_grayBuffer->getBand();
1442
1443 bandGrp += PvlKeyword("Color", "Gray");
1444
1445 bandGrp += PvlKeyword("Virtual", toString(iGrayBand));
1446 bandGrp += PvlKeyword("Physical", toString(p_cube->physicalBand(iGrayBand)));
1447
1448 if(iFilterSize && iGrayBand <= iFilterSize) {
1449 bandGrp += PvlKeyword("FilterName", filterName[iGrayBand-1]);
1450 }
1451 }
1452
1453 //start, end line and sample
1454 double sl, ss, es, el;
1455 getCubeArea(ss, es, sl, el);
1456 cubeAreaPvl += PvlKeyword("StartSample", toString(int(ss + 0.5)));
1457 cubeAreaPvl += PvlKeyword("EndSample", toString(int(es + 0.5)));
1458 cubeAreaPvl += PvlKeyword("StartLine", toString(int(sl + 0.5)));
1459 cubeAreaPvl += PvlKeyword("EndLine", toString(int(el + 0.5)));
1460 cubeAreaPvl += bandGrp;
1461 whatsThisObj += cubeAreaPvl;
1462 pWhatsThisPvl += whatsThisObj;
1463 }
1464
1473 void CubeViewport::getBandFilterName(PvlKeyword & pFilterNameKey)
1474 {
1475 // get the band info
1476 Pvl* cubeLbl = p_cube->label();
1477 PvlObject isisObj = cubeLbl->findObject("IsisCube");
1478 if (isisObj.hasGroup("BandBin")) {
1479 PvlGroup bandBinGrp = isisObj.findGroup("BandBin");
1480 if(bandBinGrp.hasKeyword("FilterName")) {
1481 pFilterNameKey =bandBinGrp.findKeyword("FilterName") ;
1482 }
1483 }
1484 }
1485
1494 void CubeViewport::getCubeArea(double & pdStartSample, double & pdEndSample,
1495 double & pdStartLine, double & pdEndLine)
1496 {
1497 viewportToCube(0, 0, pdStartSample, pdStartLine);
1498 if(pdStartSample < 1.0){
1499 pdStartSample = 1.0;
1500 }
1501 if(pdStartLine < 1.0){
1502 pdStartLine = 1.0;
1503 }
1504
1505 //end line and samples
1506 viewportToCube(viewport()->width() - 1, viewport()->height() - 1, pdEndSample, pdEndLine);
1507 if(pdEndSample > cubeSamples()){
1508 pdEndSample = cubeSamples();
1509 }
1510 if(pdEndLine > cubeLines()){
1511 pdEndLine = cubeLines();
1512 }
1513 }
1514
1520 //start, end line and sample
1521 double sl, ss, es, el;
1522 getCubeArea(ss, es, sl, el);
1523
1524 QString sBandInfo ;
1525 PvlKeyword filterNameKey;
1526 getBandFilterName(filterNameKey);
1527 int iFilterSize = filterNameKey.size();
1528
1529 // color
1530 if(p_color ) {
1531 int iRedBand = p_redBuffer->getBand();
1532 int iGreenBand = p_greenBuffer->getBand();
1533 int iBlueBand = p_blueBuffer->getBand();
1534
1535 sBandInfo = "Bands(RGB)&nbsp;Virtual = " +
1536 QString::number(iRedBand) + ", ";
1537 sBandInfo += QString::number(iGreenBand) + ", ";
1538 sBandInfo += QString::number(iBlueBand) + " ";
1539
1540 sBandInfo += "Physical = " +
1541 QString::number(p_cube->physicalBand(iRedBand)) + ", ";
1542 sBandInfo += QString::number(p_cube->physicalBand(iGreenBand)) + ", ";
1543 sBandInfo += QString::number(p_cube->physicalBand(iBlueBand));
1544
1545 if(iFilterSize) {
1546 sBandInfo += "<br>FilterName = ";
1547 if(iRedBand <= iFilterSize) {
1548 sBandInfo += QString(filterNameKey[iRedBand-1]);
1549 }
1550 else {
1551 sBandInfo += "None";
1552 }
1553 sBandInfo += ", ";
1554
1555 if(iGreenBand <= iFilterSize) {
1556 sBandInfo += QString(filterNameKey[iGreenBand-1]);
1557 }
1558 else {
1559 sBandInfo += "None";
1560 }
1561 sBandInfo += ", ";
1562
1563 if(iBlueBand <= iFilterSize) {
1564 sBandInfo += QString(filterNameKey[iBlueBand-1]);
1565 }
1566 else {
1567 sBandInfo += "None";
1568 }
1569 }
1570 }
1571 else { // gray
1572 int iGrayBand = p_grayBuffer->getBand();
1573
1574 sBandInfo = "Band(Gray)&nbsp;Virtual = " + QString::number(iGrayBand) + " ";
1575
1576 sBandInfo += "Physical = " + QString::number(p_cube->physicalBand(iGrayBand));
1577
1578 if(iFilterSize && iGrayBand <= iFilterSize) {
1579 sBandInfo += "<br>FilterName = " + QString(filterNameKey[iGrayBand-1]);
1580 }
1581 }
1582
1583 QString area =
1584 "<p><b>Visible Cube Area:</b><blockQuote> \
1585 Samples = " + QString::number(int(ss + 0.5)) + "-" +
1586 QString::number(int(es + 0.5)) + "<br> \
1587 Lines = " + QString::number(int(sl + 0.5)) + "-" +
1588 QString::number(int(el + 0.5)) + "<br> " +
1589 sBandInfo + "</blockQuote></p>";
1590
1591 QString fullWhatsThis = p_whatsThisText + area + p_cubeWhatsThisText + p_viewportWhatsThisText;
1592 setWhatsThis(fullWhatsThis);
1593 viewport()->setWhatsThis(fullWhatsThis);
1594 }
1595
1605 double CubeViewport::redPixel(int sample, int line) {
1606 p_pntBrick->SetBasePosition(sample, line, p_red.band);
1607 p_cube->read(*p_pntBrick);
1608 return (*p_pntBrick)[0];
1609 }
1610
1611
1621 double CubeViewport::greenPixel(int sample, int line) {
1622 p_pntBrick->SetBasePosition(sample, line, p_green.band);
1623 p_cube->read(*p_pntBrick);
1624 return (*p_pntBrick)[0];
1625 }
1626
1627
1637 double CubeViewport::bluePixel(int sample, int line) {
1638 p_pntBrick->SetBasePosition(sample, line, p_blue.band);
1639 p_cube->read(*p_pntBrick);
1640 return (*p_pntBrick)[0];
1641 }
1642
1643
1653 double CubeViewport::grayPixel(int sample, int line) {
1654 p_pntBrick->SetBasePosition(sample, line, p_gray.band);
1655 p_cube->read(*p_pntBrick);
1656 return (*p_pntBrick)[0];
1657 }
1658
1659
1662 return p_gray.getStretch();
1663 }
1664
1665
1668 return p_red.getStretch();
1669 };
1670
1671
1674 return p_green.getStretch();
1675 };
1676
1677
1680 return p_blue.getStretch();
1681 };
1682
1683
1694 // Handle standard mouse tracking on the viewport
1695 if(o == viewport()) {
1696 switch(e->type()) {
1697 case QEvent::Enter: {
1698 viewport()->setMouseTracking(true);
1699 emit mouseEnter();
1700 return true;
1701 }
1702
1703 case QEvent::MouseMove: {
1704 QMouseEvent *m = (QMouseEvent *) e;
1705 emit mouseMove(m->pos());
1706 unsigned int keyMask = (unsigned int)m->button() | (unsigned int)m->modifiers();
1707 emit mouseMove(m->pos(),
1708 (Qt::MouseButton)(keyMask));
1709 return true;
1710 }
1711
1712 case QEvent::Leave: {
1713 viewport()->setMouseTracking(false);
1714 emit mouseLeave();
1715 return true;
1716 }
1717
1718 case QEvent::MouseButtonPress: {
1719 QMouseEvent *m = (QMouseEvent *) e;
1720 unsigned int keyMask = (unsigned int)m->button() | (unsigned int)m->modifiers();
1721 emit mouseButtonPress(m->pos(),
1722 (Qt::MouseButton)(keyMask));
1723 return true;
1724 }
1725
1726 case QEvent::MouseButtonRelease: {
1727 QMouseEvent *m = (QMouseEvent *) e;
1728 unsigned int keyMask = (unsigned int)m->button() | (unsigned int)m->modifiers();
1729 emit mouseButtonRelease(m->pos(),
1730 (Qt::MouseButton)(keyMask));
1731 return true;
1732 }
1733
1734 case QEvent::MouseButtonDblClick: {
1735 QMouseEvent *m = (QMouseEvent *) e;
1736 emit mouseDoubleClick(m->pos());
1737 return true;
1738 }
1739
1740 default: {
1741 return false;
1742 }
1743 }
1744 }
1745 else {
1746 return QAbstractScrollArea::eventFilter(o, e);
1747 }
1748 }
1749
1750
1761 void CubeViewport::keyPressEvent(QKeyEvent *e) {
1762 if(e->key() == Qt::Key_Plus) {
1763 double scale = p_scale * 2.0;
1764 setScale(scale);
1765 e->accept();
1766 }
1767 else if(e->key() == Qt::Key_Minus) {
1768 double scale = p_scale / 2.0;
1769 setScale(scale);
1770 e->accept();
1771 }
1772 else if(e->key() == Qt::Key_Up) {
1773 moveCursor(0, -1);
1774 e->accept();
1775 }
1776 else if(e->key() == Qt::Key_Down) {
1777 moveCursor(0, 1);
1778 e->accept();
1779 }
1780 else if(e->key() == Qt::Key_Left) {
1781 moveCursor(-1, 0);
1782 e->accept();
1783 }
1784 else if(e->key() == Qt::Key_Right) {
1785 moveCursor(1, 0);
1786 e->accept();
1787 }
1788 else if ((e->key() == Qt::Key_C) &&
1789 QApplication::keyboardModifiers() &
1790 Qt::ControlModifier) {
1791
1792 //QString fileName = p_cube->fileName();
1793 QFileInfo fileName = QFileInfo(p_cube->fileName());
1794
1795 // Grabs the clipboard and copies the file name into it.
1796 QClipboard *clipboard = QApplication::clipboard();
1797 clipboard->setText(fileName.absoluteFilePath());
1798 }
1799 else {
1800 QAbstractScrollArea::keyPressEvent(e);
1801 }
1802 }
1803
1804
1812 QPoint g = QCursor::pos();
1813 QPoint v = viewport()->mapFromGlobal(g);
1814 if(v.x() < 0){
1815 return false;
1816 }
1817 if(v.y() < 0){
1818 return false;
1819 }
1820 if(v.x() >= viewport()->width()){
1821 return false;
1822 }
1823 if(v.y() >= viewport()->height()){
1824 return false;
1825 }
1826 return true;
1827 }
1828
1829
1837 QPoint g = QCursor::pos();
1838 return viewport()->mapFromGlobal(g);
1839 }
1840
1841
1849 void CubeViewport::moveCursor(int x, int y) {
1850 QPoint g = QCursor::pos();
1851 g += QPoint(x, y);
1852 QPoint v = viewport()->mapFromGlobal(g);
1853 if(v.x() < 0){
1854 return;
1855 }
1856 if(v.y() < 0){
1857 return;
1858 }
1859 if(v.x() >= viewport()->width()){
1860 return;
1861 }
1862 if(v.y() >= viewport()->height()){
1863 return;
1864 }
1865 QCursor::setPos(g);
1866 }
1867
1868
1877 QPoint g(x, y);
1878 QPoint v = viewport()->mapToGlobal(g);
1879 QCursor::setPos(v);
1880 }
1881
1882
1891 viewport()->blockSignals(true);
1892
1893 verticalScrollBar()->setValue(1);
1894 verticalScrollBar()->setMinimum(1);
1895 verticalScrollBar()->setMaximum((int)(ceil(cubeLines() * p_scale) + 0.5));
1896 verticalScrollBar()->setPageStep(viewport()->height() / 2);
1897
1898 horizontalScrollBar()->setValue(1);
1899 horizontalScrollBar()->setMinimum(1);
1900 horizontalScrollBar()->setMaximum((int)(ceil(cubeSamples() * p_scale) + 0.5));
1901 horizontalScrollBar()->setPageStep(viewport()->width() / 2);
1902
1903 if(horizontalScrollBar()->value() != x || verticalScrollBar()->value() != y) {
1904 horizontalScrollBar()->setValue(x);
1905 verticalScrollBar()->setValue(y);
1906 emit scaleChanged();
1907 }
1908
1909 QApplication::sendPostedEvents(viewport(), 0);
1910 viewport()->blockSignals(false);
1911 }
1912
1913
1920 void CubeViewport::viewGray(int band) {
1921 p_gray.band = band;
1922 p_color = false;
1923 setCaption();
1924
1925 if(!p_grayBuffer){
1927 p_cubeId);
1928 }
1929
1930 if(p_redBuffer){
1931 delete p_redBuffer;
1932 }
1933 p_redBuffer = NULL;
1934
1935 if(p_greenBuffer){
1936 delete p_greenBuffer;
1937 }
1938 p_greenBuffer = NULL;
1939
1940 if(p_blueBuffer){
1941 delete p_blueBuffer;
1942 }
1943 p_blueBuffer = NULL;
1944
1945 if(p_grayBuffer->getBand() != band) {
1946 int oldBand = p_grayBuffer->getBand();
1947
1948 if(oldBand >= 0) {
1949 if((*p_knownStretches)[oldBand - 1]) {
1950 delete(*p_knownStretches)[oldBand - 1];
1951 }
1952
1953 (*p_knownStretches)[oldBand - 1] = new Stretch(p_gray.getStretch());
1954 }
1955
1956 p_grayBuffer->setBand(band);
1957 p_gray.band = band;
1958
1959 if((*p_knownStretches)[band - 1]) {
1960 stretchGray(*(*p_knownStretches)[band - 1]);
1961 }
1962 else {
1963 p_grayBuffer->addStretchAction();
1964 }
1965 }
1966
1967 if(p_camera) {
1968 p_camera->SetBand(band);
1969 }
1970
1971 viewport()->repaint();
1972 }
1973
1974
1976 for(int stretch = 0; stretch < p_knownStretches->size(); stretch++) {
1977 if((*p_knownStretches)[stretch]) {
1978 delete(*p_knownStretches)[stretch];
1979 (*p_knownStretches)[stretch] = NULL;
1980 }
1981 }
1982 }
1983
1984
1986 for(int index = 0; index < p_knownStretches->size(); index ++) {
1987 if((*p_knownStretches)[index]) {
1988 delete(*p_knownStretches)[index];
1989 }
1990
1991 (*p_knownStretches)[index] = new Stretch(stretch);
1992 }
1993 }
1994
1995
2004 void CubeViewport::viewRGB(int rband, int gband, int bband) {
2005 p_red.band = rband;
2006 p_green.band = gband;
2007 p_blue.band = bband;
2008 p_color = true;
2009 setCaption();
2010
2011 if(!p_redBuffer) {
2013 }
2014
2015 if(!p_greenBuffer) {
2017 }
2018
2019 if(!p_blueBuffer) {
2021 }
2022
2023 if(p_redBuffer->getBand() != rband) {
2024 int oldBand = p_redBuffer->getBand();
2025
2026 // Remember current stretch for future band changes
2027 if(oldBand >= 0) {
2028 if((*p_knownStretches)[oldBand - 1]) {
2029 delete(*p_knownStretches)[oldBand - 1];
2030 }
2031
2032 (*p_knownStretches)[oldBand - 1] = new Stretch(p_red.getStretch());
2033 }
2034
2035 p_redBuffer->setBand(rband);
2036 p_red.band = rband;
2037
2038 if((*p_knownStretches)[rband - 1]) {
2039 p_red.setStretch(*(*p_knownStretches)[rband - 1]);
2040 }
2041 else {
2042 p_redBuffer->addStretchAction();
2043 }
2044 }
2045
2046 if(p_greenBuffer->getBand() != gband) {
2047 int oldBand = p_greenBuffer->getBand();
2048
2049 // Remember current stretch for future band changes
2050 if(oldBand >= 0) {
2051 if((*p_knownStretches)[oldBand - 1]) {
2052 delete(*p_knownStretches)[oldBand - 1];
2053 }
2054
2055 (*p_knownStretches)[oldBand - 1] = new Stretch(p_green.getStretch());
2056 }
2057
2058 p_greenBuffer->setBand(gband);
2059 p_green.band = gband;
2060
2061 if((*p_knownStretches)[gband - 1]) {
2062 p_green.setStretch(*(*p_knownStretches)[gband - 1]);
2063 }
2064 else {
2065 p_greenBuffer->addStretchAction();
2066 }
2067 }
2068
2069 if(p_blueBuffer->getBand() != bband) {
2070 int oldBand = p_blueBuffer->getBand();
2071
2072 // Remember current stretch for future band changes
2073 if(oldBand >= 0) {
2074 if((*p_knownStretches)[oldBand - 1]) {
2075 delete(*p_knownStretches)[oldBand - 1];
2076 }
2077
2078 (*p_knownStretches)[oldBand - 1] = new Stretch(p_blue.getStretch());
2079 }
2080
2081 p_blueBuffer->setBand(bband);
2082 p_blue.band = bband;
2083
2084 if((*p_knownStretches)[bband - 1]) {
2085 p_blue.setStretch(*(*p_knownStretches)[bband - 1]);
2086 }
2087 else {
2088 p_blueBuffer->addStretchAction();
2089 }
2090 }
2091
2092 if(p_grayBuffer){
2093 delete p_grayBuffer;
2094 }
2095 p_grayBuffer = NULL;
2096
2097 if(p_camera) {
2098 p_camera->SetBand(rband);
2099 }
2100 }
2101
2102
2109 void CubeViewport::stretchGray(const QString &string) {
2110 Stretch stretch;
2111 stretch.Parse(string);
2112 stretchGray(stretch);
2113 }
2114
2115
2121 void CubeViewport::stretchRed(const QString &string) {
2122 Stretch stretch;
2123 stretch.Parse(string);
2124 stretchRed(stretch);
2125 }
2126
2127
2133 void CubeViewport::stretchGreen(const QString &string) {
2134 Stretch stretch;
2135 stretch.Parse(string);
2136 stretchGreen(stretch);
2137 }
2138
2139
2145 void CubeViewport::stretchBlue(const QString &string) {
2146 Stretch stretch;
2147 stretch.Parse(string);
2148 stretchBlue(stretch);
2149 }
2150
2151
2156 if(!p_globalStretches){
2157 return;
2158 }
2159
2160 if(isGray()) {
2161 if((*p_globalStretches)[grayBand() - 1]) {
2163 }
2164 }
2165 else {
2166 if((*p_globalStretches)[redBand() - 1]) {
2168 }
2169
2170 if((*p_globalStretches)[greenBand() - 1]) {
2172 }
2173
2174 if((*p_globalStretches)[blueBand() - 1]) {
2176 }
2177 }
2178 }
2179
2180
2186 void CubeViewport::stretchGray(const Stretch &stretch) {
2187 // Assume first stretch is always the global stretch (and it should be)
2188 if((*p_globalStretches)[grayBand() - 1] == NULL && stretch.Pairs()) {
2189 (*p_globalStretches)[grayBand() - 1] = new Stretch(stretch);
2190 }
2191
2192 p_gray.setStretch(stretch);
2193
2194 Stretch newRed(p_red.getStretch());
2195 newRed.CopyPairs(stretch);
2196 p_red.setStretch(newRed);
2197
2198 Stretch newGreen(p_green.getStretch());
2199 newGreen.CopyPairs(stretch);
2200 p_green.setStretch(newGreen);
2201
2202 Stretch newBlue(p_blue.getStretch());
2203 newBlue.CopyPairs(stretch);
2204 p_blue.setStretch(newBlue);
2205
2206 paintPixmap();
2207 viewport()->update();
2208 }
2209
2210
2216 void CubeViewport::stretchRed(const Stretch &stretch) {
2217 p_red.setStretch(stretch);
2218
2219 // Assume first stretch is always the global stretch (and it should be)
2220 if((*p_globalStretches)[redBand() - 1] == NULL && stretch.Pairs()) {
2221 (*p_globalStretches)[redBand() - 1] = new Stretch(p_red.getStretch());
2222 }
2223
2224 paintPixmap();
2225 viewport()->update();
2226 }
2227
2228
2235 p_green.setStretch(stretch);
2236
2237 // Assume first stretch is always the global stretch (and it should be)
2238 if((*p_globalStretches)[greenBand() - 1] == NULL && stretch.Pairs()) {
2239 (*p_globalStretches)[greenBand() - 1] = new Stretch(p_green.getStretch());
2240 }
2241
2242 paintPixmap();
2243 viewport()->update();
2244 }
2245
2246
2252 void CubeViewport::stretchBlue(const Stretch &stretch) {
2253 p_blue.setStretch(stretch);
2254
2255 // Assume first stretch is always the global stretch (and it should be)
2256 if((*p_globalStretches)[blueBand() - 1] == NULL && stretch.Pairs()) {
2257 (*p_globalStretches)[blueBand() - 1] = new Stretch(p_blue.getStretch());
2258 }
2259
2260 paintPixmap();
2261 viewport()->update();
2262 }
2263
2264
2272 double CubeViewport::fitScale() const {
2273 double sampScale = (double) viewport()->width() / (double) cubeSamples();
2274 double lineScale = (double) viewport()->height() / (double) cubeLines();
2275 double scale = sampScale < lineScale ? sampScale : lineScale;
2276// scale = floor(scale * 100.0) / 100.0;
2277 return scale;
2278 }
2279
2280
2288 double scale = (double) viewport()->width() / (double) cubeSamples();
2289
2290// scale = floor(scale * 100.0) / 100.0;
2291 return scale;
2292 }
2293
2301 double scale = (double) viewport()->height() / (double) cubeLines();
2302
2303// scale = floor(scale * 100.0) / 100.0;
2304 return scale;
2305 }
2306
2315 //start sample/line and end sample/line
2316 double ss, sl, es, el;
2317 ss = (double)(rect.left()) - 1.;
2318 sl = (double)(rect.top()) - 1.;
2319 es = (double)(rect.right()) + 1.;
2320 el = (double)(rect.bottom()) + 1.;
2321 if(ss < 1){
2322 ss = 0.5;
2323 }
2324 if(sl < 1){
2325 sl = 0.5;
2326 }
2327 if(es > cube()->sampleCount()){
2328 es = cube()->sampleCount() + 0.5;
2329 }
2330 if(el > cube()->lineCount()){
2331 el = cube()->lineCount() + 0.5;
2332 }
2333
2334 //start x/y and end x/y
2335 int sx, sy, ex, ey;
2336
2337 cubeToViewport(ss, sl, sx, sy);
2338 cubeToViewport(es, el, ex, ey);
2339 if(sx < 0){
2340 sx = 0;
2341 }
2342 if(sy < 0){
2343 sy = 0;
2344 }
2345 if(ex > viewport()->width()){
2346 ex = viewport()->width();
2347 }
2348 if(ey > viewport()->height()){
2349 ey = viewport()->height();
2350 }
2351 QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1);
2352
2353 p_updatingBuffers = true;
2354 if(p_grayBuffer){
2355 p_grayBuffer->fillBuffer(vpRect);
2356 }
2357 if(p_redBuffer){
2358 p_redBuffer->fillBuffer(vpRect);
2359 }
2360 if(p_greenBuffer){
2361 p_greenBuffer->fillBuffer(vpRect);
2362 }
2363 if(p_blueBuffer){
2364 p_blueBuffer->fillBuffer(vpRect);
2365 }
2366 p_updatingBuffers = false;
2367
2369 }
2370
2371
2378 PvlGroup trackingGroup = p_cube->group("Tracking");
2379 //Because the tracking group does not have a path, get the path from the main cube
2380 FileName cubeName(p_cube->fileName());
2381 QString trackingCubeName = trackingGroup.findKeyword("Filename")[0];
2382 FileName trackingCubeFileName(cubeName.path() + "/" + trackingCubeName);
2383 Cube *trackingCube = new Cube(trackingCubeFileName);
2384 p_trackingCube = trackingCube;
2385 }
2386
2387
2394 void CubeViewport::changeCursor(QCursor cursor) {
2395 viewport()->setCursor(cursor);
2396 }
2397
2398
2399 CubeViewport::BandInfo::BandInfo() : band(1), stretch(NULL) {
2400 stretch = new CubeStretch;
2401 stretch->SetNull(0.0);
2402 stretch->SetLis(0.0);
2403 stretch->SetLrs(0.0);
2404 stretch->SetHis(255.0);
2405 stretch->SetHrs(255.0);
2406 stretch->SetMinimum(0.0);
2407 stretch->SetMaximum(255.0);
2408 };
2409
2410
2411 CubeViewport::BandInfo::BandInfo(const CubeViewport::BandInfo &other) :
2412 band(other.band) {
2413 stretch = NULL;
2414 stretch = new CubeStretch(*other.stretch);
2415 }
2416
2417
2419 if(stretch) {
2420 delete stretch;
2421 stretch = NULL;
2422 }
2423 }
2424
2425
2429
2430
2432 *stretch = newStretch;
2433 }
2434
2435
2437 CubeViewport::BandInfo other) {
2438
2439 stretch = NULL;
2440 stretch = new CubeStretch;
2441 *stretch = *other.stretch;
2442 band = other.band;
2443
2444 return *this;
2445 }
2446
2447}
Buffer for containing a three dimensional section of an image.
Definition Brick.h:45
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
Definition Buffer.cpp:146
int LineDimension() const
Returns the number of lines in the shape buffer.
Definition Buffer.h:79
int SampleDimension() const
Returns the number of samples in the shape buffer.
Definition Buffer.h:70
int Sample(const int index=0) const
Returns the sample position associated with a shape buffer index.
Definition Buffer.cpp:128
Encapsulation of Cube I/O with Change Notifications.
IO Handler for Isis Cubes.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:2008
int sampleCount() const
Definition Cube.cpp:2081
Stores stretch information for a cube.
Definition CubeStretch.h:27
const BandInfo & operator=(BandInfo other)
The BandInfo for the Cube.
CubeStretch getStretch() const
void setStretch(const Stretch &newStretch)
CubeStretch * stretch
The Stretch.
bool p_cubeShown
Is the cube visible?
void stretchGray(const QString &string)
Apply stretch pairs to gray band.
void getCubeArea(double &pdStartSample, double &pdEndSample, double &pdStartLine, double &pdEndLine)
Get Cube area corresponding to the viewport's dimension.
double bluePixel(int sample, int line)
Gets the blue pixel.
void updateScrollBars(int x, int y)
Update the scroll bar.
CubeViewport(Cube *cube, CubeDataThread *cdt=0, QWidget *parent=0)
Constructor for the CubeViewport.
Brick * p_pntBrick
Bricks for every color.
double scale() const
void stretchBlue(const QString &string)
Apply stretch pairs to blue bands.
Cube * p_cube
The cube associated with the viewport.
CubeStretch grayStretch() const
Return the gray band stretch.
void doneWithData(int, const Isis::Brick *)
Emitted when a brick is no longer needed, should only be sent to cube data thread.
void showEvent(QShowEvent *)
This method is called to initially show the viewport.
void getBandFilterName(PvlKeyword &pFilterNameKey)
Get Band Filter name from the Isis cube label.
Brick * p_redBrick
Bricks for every color.
int cubeLines() const
Return the number of lines in the cube.
void discardChanges(CubeViewport *)
Emitted when changes should be discarded.
double greenPixel(int sample, int line)
Gets the green pixel.
int greenBand() const
ViewportBuffer * p_grayBuffer
Viewport Buffer to manage gray band.
int cubeBands() const
Return the number of bands in the cube.
QString p_whatsThisText
The text for What's this.
ViewportBuffer * p_redBuffer
Viewport Buffer to manage red band.
bool p_color
Is the viewport in color?
bool p_updatingBuffers
Changing RGB and need to not repaint pixmap?
void setCursorPosition(int x, int y)
Set the cursor position to x/y in the viewport.
QList< QRect * > * p_pixmapPaintRects
A list of rects that the viewport buffers have requested painted.
CubeStretch redStretch() const
Return the red band stretch.
void scaleChanged()
Emitted when zoom factor changed just before the repaint event.
int redBand() const
bool p_thisOwnsCubeData
if true then this owns the CubeDataThread, and should thus delete it
void setCube(Cube *cube)
This method sets the viewports cube.
virtual void resizeEvent(QResizeEvent *e)
The viewport is being resized.
virtual void paintEvent(QPaintEvent *e)
Repaint the viewport.
void contentsToCube(int x, int y, double &sample, double &line) const
Turns contents to a cube.
QSize sizeHint() const
Make viewports show up as 512 by 512.
void changeCursor(QCursor cursor)
Allows users to change the cursor type on the viewport.
Projection * p_projection
The projection from the cube.
void updateWhatsThis()
Update the What's This text.
virtual bool eventFilter(QObject *o, QEvent *e)
Event filter to watch for mouse events on viewport.
bool cursorInside() const
Is cursor inside viewport.
QPoint cursorPosition() const
Return the cursor position in the viewport.
virtual ~CubeViewport()
Deconstructor for the Cubeviewport.
virtual void viewRGB(int redBand, int greenBand, int blueBand)
View cube as color.
int p_comboIndex
Current element chosen from combo box.
double fitScaleHeight() const
Determine the scale of cube in heighth to fit in the viewport.
void paintPixmapRects()
Goes through the list of requested paints, from the viewport buffer, and paints them.
int cubeSamples() const
Return the number of samples in the cube.
void mouseDoubleClick(QPoint)
Emitted when double click happens.
void progressComplete()
Emitted when the current progress is complete (100)
void stretchKnownGlobal()
List<Tool *> p This stretches to the global stretch.
QPixmap p_pixmap
The qpixmap.
void stretchGreen(const QString &string)
Apply stretch pairs to green bands.
void scrollContentsBy(int dx, int dy)
Scroll the viewport contents by dx/dy screen pixels.
Brick * p_grnBrick
Bricks for every color.
QString p_viewportWhatsThisText
The text for the viewport's what's this.
double grayPixel(int sample, int line)
Gets the gray pixel.
Cube * trackingCube() const
void setTrackingCube()
Finds the Tracking group from p_cube and stores the tracking cube name so that we can grab it in Adva...
void cubeChanged(bool changed)
This method is called when the cube has changed or changes have been finalized.
void cubeToContents(double sample, double line, int &x, int &y) const
Turns a cube into contents.
bool p_saveEnabled
Has the cube changed?
QString p_cubeWhatsThisText
The text for the cube's What's this.
virtual void keyPressEvent(QKeyEvent *e)
Process arrow keystrokes on cube.
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
QColor p_bgColor
The color to paint the background of the viewport.
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
void mouseButtonRelease(QPoint, Qt::MouseButton)
Emitted when mouse button released.
BandInfo p_blue
Blue band info.
void mouseButtonPress(QPoint, Qt::MouseButton)
Emitted when mouse button pressed.
void mouseLeave()
Emitted when the mouse leaves the viewport.
double fitScale() const
Determine the scale that causes the full cube to fit in the viewport.
CubeDataThread * p_cubeData
Does all the cube I/O.
void stretchRed(const QString &string)
Apply stretch pairs to red bands.
bool confirmClose()
This method should be called during a close event that would cause this viewport to close.
Brick * p_bluBrick
Bricks for every color.
CubeStretch greenStretch() const
Return the green band stretch.
BandInfo p_green
Green band info.
void saveChanges(CubeViewport *)
Emitted when changes should be saved.
void setScale(double scale)
Change the scale of the cube to the given parameter value.
void forgetStretches()
Resets all remembered stretches.
int grayBand() const
Camera * p_camera
The camera from the cube.
ViewportBuffer * p_greenBuffer
Viewport Buffer to manage green band.
QTimer * p_progressTimer
Activated to update progress bar.
QImage * p_image
The qimage.
void paintPixmap()
Paint the whole pixmap.
void getAllWhatsThisInfo(Pvl &pWhatsThisPvl)
Get All WhatsThis info - viewport, cube, area in PVL format.
BandInfo p_gray
Gray band info.
Cube * cube() const
void mouseEnter()
Emitted when the mouse enters the viewport.
int p_comboCount
Number of elements in band bin combo box.
double redPixel(int sample, int line)
Gets the red pixel.
void enableProgress()
This restarts the progress bar.
virtual void viewGray(int band)
View cube as gray.
BandInfo p_red
Red band info.
void windowTitleChanged()
Emitted when window title changes.
UniversalGroundMap * p_groundMap
The universal ground map from the cube.
void scrollBy(int dx, int dy)
Move the scrollbars by dx/dy screen pixels.
QVector< Stretch * > * p_globalStretches
Global stretches for each stretched band.
void shiftPixmap(int dx, int dy)
Shifts the pixels on the pixmap without reading new data.
void progressChanged(int)
Emitted with current progress (0 to 100) when working.
QVector< Stretch * > * p_knownStretches
Stretches for each previously stretched band.
void onProgressTimer()
This updates the progress bar visually.
void screenPixelsChanged()
Emitted when cube pixels that should be on the screen change.
Brick * p_gryBrick
Bricks for every color.
void setAllBandStretches(Stretch stretch)
Sets a stretch for all bands.
void moveCursor(int x, int y)
Move the cursor by x,y if possible.
int p_cubeId
Cube ID given from cube data thread for I/O.
void cubeContentsChanged(QRect rect)
Calle dhwen the contents of the cube changes.
bool p_paintPixmap
Paint the pixmap?
bool isGray() const
void setCaption()
Change the caption on the viewport title bar.
double p_scale
The scale number.
virtual void cubeDataChanged(int cubeId, const Isis::Brick *)
This method updates the internal viewport buffer based on changes in cube DN values.
int blueBand() const
void mouseMove(QPoint)
Emitted when the mouse moves.
double fitScaleWidth() const
Determine the scale of cube in the width to fit in the viewport.
CubeStretch blueStretch() const
Return the blue band stretch.
void center(int x, int y)
Bring the cube pixel under viewport x/y to the center.
ViewportBuffer * p_blueBuffer
Viewport Buffer to manage blue band.
void bufferUpdated(QRect rect)
This method is called by ViewportBuffer upon successful completion of all operations and gives the ap...
Pixel value mapper.
Definition Stretch.h:58
void CopyPairs(const Stretch &other)
Copies the stretch pairs from another Stretch object, but maintains special pixel values.
Definition Stretch.cpp:393
void Parse(const QString &pairs)
Parses a string of the form "i1:o1 i2:o2...iN:oN" where each i:o represents an input:output pair.
Definition Stretch.cpp:182
void SetNull(const double value)
Sets the mapping for NULL pixels.
Definition Stretch.h:94
int Pairs() const
Returns the number of stretch pairs.
Definition Stretch.h:162
Universal Ground Map.
Reads and stores visible DN values.
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
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.
Namespace for the standard library.