Isis 3 Programmer Reference
ChipViewport.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "ChipViewport.h"
10
11#include <iostream>
12
13#include <QMessageBox>
14#include <QPainter>
15
16#include "ControlMeasure.h"
17#include "ControlNet.h"
18#include "ControlPoint.h"
19#include "Cube.h"
20#include "CubeViewport.h"
21#include "SerialNumber.h"
22#include "Stretch.h"
23
24namespace Isis {
25
33 ChipViewport::ChipViewport(int width, int height, QWidget *parent) : QWidget(parent) {
34
35 setFixedSize(width, height);
36 setBackgroundRole(QPalette::Dark);
37// setFocusPolicy(Qt::StrongFocus);
38
39 m_width = width;
40 m_height = height;
41 m_zoomFactor = 1.0;
42 m_rotation = 0;
43 m_geomIt = false;
44 m_tempView = NULL;
45 m_cross = true;
46 m_circle = false;
47 m_chip = NULL;
48 m_chipCube = NULL;
49 m_matchChip = NULL;
50 m_matchChipCube = NULL;
51 m_image = NULL;
52 m_image = new QImage(512, 512, QImage::Format_RGB32);
53 m_image->fill(Qt::black);
54 m_controlNet = NULL;
55 m_stretchLocked = false;
56 m_stretch = NULL;
57
58 m_stretch = new Stretch;
59 }
60
61
66 if (m_stretch) {
67 delete m_stretch;
68 m_stretch = NULL;
69 }
70 }
71
72
83 bool ChipViewport::cubeToViewport(double samp, double line,
84 int &x, int &y) {
85
86 m_chip->SetCubePosition(samp, line);
87 x = ((int) m_chip->ChipSample()) - 1;
88 y = ((int) m_chip->ChipLine()) - 1;
89
90 return m_chip->IsInsideChip(samp, line);
91 }
92
93
108 void ChipViewport::setChip(Chip *chip, Cube *chipCube) {
109 // Is the chip usable?
110 if (chip == NULL || chipCube == NULL) {
112 "Can not view NULL chip pointer",
113 _FILEINFO_);
114 }
115
116 m_zoomFactor = 1.0;
117 m_rotation = 0;
118
119 m_chip = chip;
120 m_chipCube = chipCube;
121 if (m_image != NULL)
122 delete m_image;
123 m_image = new QImage(chip->Samples(), chip->Lines(), QImage::Format_RGB32);
124
125 autoStretch();
127 }
128
129
135 paintImage();
136 update();
137 }
138
139
147
148 if (!cvp || !m_chipCube)
149 return;
150
151 // only stretch if the CubeViewport is opened to the same cube as we are,
152 // otherwise the signal was meant for a different ChipViewport!
153 if (cvp->cube()->fileName() == m_chipCube->fileName()) {
154
155 // if user right clicked in the CubeViewport then we get a SIGNAL with a
156 // NULL Stretch. This is used to signify that we need to restretch on our
157 // own (go back to global).
158 if (!newStretch) {
160 paintImage();
161 update();
162 }
163 else {
164 *m_stretch = *newStretch;
165 m_gray.stretch = *newStretch;
166 paintImage();
167 update();
168 }
169 }
170 }
171
172
179 if (newStatus == 0)
180 m_stretchLocked = false;
181 else
182 m_stretchLocked = true;
183 }
184
185
193 void ChipViewport::computeStretch(Stretch &stretch, bool force) {
194 if (m_stretchLocked && !force) {
195 stretch = *m_stretch;
196 }
197 else {
198 Statistics stats;
199 for (int line = 1; line < m_chip->Lines(); line++) {
200 for (int samp = 1; samp < m_chip->Samples(); samp++) {
201 double value = m_chip->GetValue(samp, line);
202 stats.AddData(&value, 1);
203 }
204 }
205
206 Histogram hist(stats.BestMinimum(), stats.BestMaximum());
207 for (int line = 1; line <= m_chip->Lines(); line++) {
208 for (int samp = 1; samp <= m_chip->Samples(); samp++) {
209 double value = m_chip->GetValue(samp, line);
210 hist.AddData(&value, 1);
211 }
212 }
213
214 stretch.ClearPairs();
215 if (hist.Percent(0.5) != hist.Percent(99.5)) {
216 stretch.AddPair(hist.Percent(0.5), 0.0);
217 stretch.AddPair(hist.Percent(99.5), 255.0);
218 }
219 else {
220 stretch.AddPair(-DBL_MAX, 0.0);
221 stretch.AddPair(DBL_MAX, 255.0);
222 }
223
224 *m_stretch = stretch;
225 }
226 }
227
228
233 //TODO ??? Need something similar to CubeViewport clipping, so that
234 // at edge of image, fill viewport w/ black
235 for (int y = 0; y < m_chip->Lines(); y++) {
236 QRgb *rgb = (QRgb *) m_image->scanLine(y);
237 int r, g, b;
238 for (int x = 0; x < m_chip->Samples(); x++) {
239 r = g = b = (int) m_gray.stretch.Map(m_chip->GetValue(x + 1, y + 1));
240 rgb[x] = qRgb(r, g, b);
241 }
242 }
243 repaint();
244
245 }
246
247
260 void ChipViewport::paintEvent(QPaintEvent *e) {
261
262 QPainter painter(this);
263
264 if (m_tempView != NULL) {
265 painter.drawImage(0, 0, *(m_tempView->m_image));
266 }
267 else {
268 painter.drawImage(0, 0, *m_image);
269 }
270
271 if (m_cross == true) {
272 painter.setPen(Qt::red);
273 painter.drawLine(0, (m_height - 1) / 2, m_width - 1, (m_height - 1) / 2);
274 painter.drawLine((m_width - 1) / 2, 0, (m_width - 1) / 2, m_height - 1);
275 }
276
277 if (m_circle == true) {
278 painter.setPen(Qt::red);
279 painter.drawEllipse((m_height - 1) / 2 - m_circleSize / 2,
280 (m_width - 1) / 2 - m_circleSize / 2,
282 }
283
284 QString serialNumber = m_chipCube? SerialNumber::Compose(*m_chipCube) : QString();
285 if (m_controlNet && !serialNumber.isEmpty()
286 && m_controlNet->GetCubeSerials().contains(serialNumber)) {
287 // draw measure locations if we have a control network
288 // If the serial number is Unknown, we probably have a ground source
289 // file or level 2 which means it does not exist in the network
290 //TODO Is there a better way to handle this?
291 if (m_showPoints && serialNumber.compare("Unknown") &&
292 m_controlNet->GetNumPoints() != 0) {
293 QList<ControlMeasure *> measures =
294 m_controlNet->GetMeasuresInCube(serialNumber);
295 // loop through all points in the control net
296 for (int i = 0; i < measures.count(); i++) {
297 ControlMeasure *m = measures[i];
298 // Find the measurments on the viewport
299 double samp = m->GetSample();
300 double line = m->GetLine();
301 int x, y;
302
303 cubeToViewport(samp, line, x, y);
304 // Determine pen color
305 // if the point or measure is ignored set to yellow
306 if (m->Parent()->IsIgnored() ||
307 (!m->Parent()->IsIgnored() && m->IsIgnored())) {
308 painter.setPen(QColor(255, 255, 0)); // set point marker yellow
309 }
310 // check for ground measure
311 else if (m->Parent()->GetType() == ControlPoint::Fixed) {
312 painter.setPen(Qt::magenta);// set point marker magenta
313 }
314 else {
315 painter.setPen(Qt::green); // set all other point markers green
316 }
317
318 // draw points which are not under cross
319 if (x != (m_width - 1) / 2 || y != (m_height - 1) / 2) {
320 painter.drawLine(x - 5, y, x + 5, y);
321 painter.drawLine(x, y - 5, x, y + 5);
322 }
323 }
324 }
325 }
326
327 m_tempView = NULL;
328 //painter.end();
329
330 }
331
332
339 m_tempView = &newView;
340 update();
341 }
342
343
353
354
364
365
370 int x, y;
371 x = m_chip->TackSample();
372 y = m_chip->TackLine() - 1;
373 // Reload with new cube position
374 m_chip->SetChipPosition((double)x, (double)y);
376 }
377
378
383 int x, y;
384 x = m_chip->TackSample();
385 y = m_chip->TackLine() + 1;
386 // Reload with new cube position
387 m_chip->SetChipPosition((double)x, (double)y);
389 }
390
391
396 int x, y;
397 x = m_chip->TackSample() - 1;
398 y = m_chip->TackLine();
399 // Reload with new cube position
400 m_chip->SetChipPosition((double)x, (double)y);
402 }
403
404
409 int x, y;
410 x = m_chip->TackSample() + 1;
411 y = m_chip->TackLine();
412 // Reload with new cube position
413 m_chip->SetChipPosition((double)x, (double)y);
415 }
416
417
422 m_zoomFactor /= 2.0;
423 reloadChip();
424 }
425
426
431 m_zoomFactor *= 2.0;
432 reloadChip();
433 }
434
435
440 m_zoomFactor = 1.0;
441 reloadChip();
442 }
443
444
450 void ChipViewport::zoom(double zoomFactor) {
452 reloadChip();
453 }
454
455
462 return m_zoomFactor;
463 }
464
465
472 void ChipViewport::refreshView(double tackSample, double tackLine) {
474 }
475
476
482 void ChipViewport::enterEvent(QEvent *e) {
483 setFocus();
484 }
485
486
492 void ChipViewport::keyPressEvent(QKeyEvent *e) {
493
494 int x, y;
495 x = m_chip->TackSample();
496 y = m_chip->TackLine();
497 if (e->key() == Qt::Key_Up) {
498 y--;
499 }
500 else if (e->key() == Qt::Key_Down) {
501 y++;
502 }
503 else if (e->key() == Qt::Key_Left) {
504 x--;
505 }
506 else if (e->key() == Qt::Key_Right) {
507 x++;
508 }
509 else {
510 QWidget::keyPressEvent(e);
511 return;
512 }
513
514 // Reload with new cube position
515 m_chip->SetChipPosition((double)x, (double)y);
517 emit userMovedTackPoint();
518 }
519
520
530 void ChipViewport::mousePressEvent(QMouseEvent *event) {
531
532 QPoint p = event->pos();
533 if (event->button() == Qt::LeftButton) {
534 // Reload with new cube position
535 m_chip->SetChipPosition((double)p.x(), (double)p.y());
537 emit userMovedTackPoint();
538 // This was added when the scrolled area was added to the QnetTool.
539 // For some reason when clicking in the ChipViewport, focus would be
540 // lost and the arrow keys would no longer work.
541 //TODO Is this the correct way to fix this, why is it happening?
542 setFocus();
543 }
544 }
545
546
552 void ChipViewport::setPoints(bool checked) {
553
554 if (checked == m_showPoints)
555 return;
556
557 m_showPoints = checked;
558 repaint();
559
560 }
561
562
568 void ChipViewport::setCross(bool checked) {
569
570 if (checked == m_cross)
571 return;
572
573 m_cross = checked;
574 repaint();
575
576 }
577
578
584 void ChipViewport::setCircle(bool checked) {
585
586 if (checked == m_circle)
587 return;
588
589 m_circle = checked;
590 repaint();
591 }
592
593
600
601 m_circleSize = size;
602 repaint();
603
604 }
605
606
617 void ChipViewport::geomChip(Chip *matchChip, Cube *matchChipCube) {
618
619 m_geomIt = true;
620 m_matchChip = matchChip;
621 m_matchChipCube = matchChipCube;
622 try {
623 m_chip->Load(*m_chipCube, *matchChip, *matchChipCube);
624// m_chip->ReLoad(*matchChip,m_zoomFactor);
625 }
626 catch (IException &e) {
627 QString msg = "Cannot geom chip.\n";
628 msg += e.toString();
629 QMessageBox::information((QWidget *)parent(), "Error", msg);
630 return;
631 }
632
633 //TODO ??? Can these be added to paintEvent method ???
634 autoStretch();
635 }
636
637
646
647 m_geomIt = false;
648 try {
650 }
651 catch (IException &e) {
652 QString msg = "Cannot load no geom chip.\n";
653 msg += e.toString();
654 QMessageBox::information((QWidget *)parent(), "Error", msg);
655 return;
656 }
657
658 //TODO ??? Can these be added to paintEvent method ???
659 autoStretch();
660 }
661
662
673 void ChipViewport::rotateChip(int rotation) {
674
675 m_rotation = -rotation;
676 try {
677 m_chip->Load(*m_chipCube, -rotation, m_zoomFactor);
678 }
679 catch (IException &e) {
680 QString msg = "Cannot load rotated chip.\n";
681 msg += e.toString();
682 QMessageBox::information((QWidget *)parent(), "Error", msg);
683 return;
684 }
685
686 //TODO ??? Can these be added to paintEvent method ???
687 autoStretch();
688 }
689
690
703 void ChipViewport::reloadChip(double tackSample, double tackLine) {
704
705 // Is the chip usable?
706 if (m_chip == NULL) {
708 "Can not view NULL chip pointer",
709 _FILEINFO_);
710 }
711
712 if (tackSample != 0. && tackLine != 0.)
714 if (m_geomIt) {
715 if (m_matchChip == NULL) {
716 throw IException(IException::User, "Invalid match chip", _FILEINFO_);
717 }
718 try {
720 }
721 catch (IException &e) {
722 QString msg = "Cannot reload chip.\n";
723 msg += e.toString();
724 QMessageBox::information((QWidget *)parent(), "Error", msg);
725 return;
726 }
727// m_chip->ReLoad(*m_matchChip,m_zoomFactor);
728 }
729 else {
730 try {
732 }
733 catch (IException &e) {
734 QString msg = "Cannot reload chip.\n";
735 msg += e.toString();
736 QMessageBox::information((QWidget *)parent(), "Error", msg);
737 return;
738 }
739 }
740
741
742 //TODO ??? Can these be added to paintEvent method ???
743 autoStretch();
744
745 // emit signal indicating tack point changed so that the TieTool
746 // can update the sample/line label.
748 }
749}
A small chip of data used for pattern matching.
Definition Chip.h:86
double CubeLine() const
Definition Chip.h:210
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition Chip.h:145
int Samples() const
Definition Chip.h:99
int TackSample() const
This method returns a chip's fixed tack sample; the middle of the chip.
Definition Chip.h:176
bool IsInsideChip(double sample, double line)
Definition Chip.cpp:162
int Lines() const
Definition Chip.h:106
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
Definition Chip.cpp:643
double ChipSample() const
Definition Chip.h:219
double ChipLine() const
Definition Chip.h:226
void TackCube(const double cubeSample, const double cubeLine)
This sets which cube position will be located at the chip tack position.
Definition Chip.cpp:182
double CubeSample() const
Definition Chip.h:203
void Load(Cube &cube, const double rotation=0.0, const double scale=1.0, const int band=1)
Load cube data into the Chip.
Definition Chip.cpp:203
int TackLine() const
This method returns a chip's fixed tack line; the middle of the chip.
Definition Chip.h:187
void SetCubePosition(const double sample, const double line)
Compute the position of the chip given a cube coordinate.
Definition Chip.cpp:660
Stretch stretch
Stretch for the band BandInfo constructor.
Viewport for Isis Chips.
bool m_stretchLocked
Whether or not to lock the stretch when transforming.
Cube * m_chipCube
The chip's cube.
void loadView(ChipViewport &newView)
Load with another ChipViewport, used for blinking.
ChipViewport * m_tempView
Temporary viewport.
int m_rotation
Rotation.
void setPoints(bool checked)
Slot to set whether control points are drawn.
Stretch * m_stretch
Current stretch on the chip viewport.
int m_width
Chip width.
void setCircle(bool checked)
Slot to change state of circle.
virtual ~ChipViewport()
Destructor.
void enterEvent(QEvent *e)
If mouse enters, make sure key events are processed w/o clicking.
void paintImage()
Paints the chip viewport after the chip has been updated.
Chip * chip() const
Return chip.
Chip * m_matchChip
The matching chip.
double m_zoomFactor
Zoom Factor.
ChipViewport(int width, int height, QWidget *parent=0)
Construct an empty viewport.
double tackSample()
Return the position of cube under cross hair.
void zoomOut()
Zoom out.
double tackLine()
Returns tack line.
void zoom(double zoomFactor)
Zoom by a specified factor.
void nogeomChip()
Slot to un-geom chip (revert geometry transformation)
void rotateChip(int rotation)
Slot to rotate chip.
double zoomFactor()
Return the zoom factor.
bool m_geomIt
geomIt?
Chip * m_chip
The chip.
void paintEvent(QPaintEvent *e)
Repaint the viewport.
bool m_cross
Draw crosshair.
void computeStretch(Stretch &stretch, bool force=false)
Compute automatic stretch for a portion of the cube.
void panLeft()
Pan left.
void panRight()
Pan right.
void panUp()
Pan up.
Cube * m_matchChipCube
The matching chip's cube.
int m_circleSize
Circle size.
void reloadChip(double tackSample=0., double tackLine=0.)
Reloads the chip at the given tack point on the cube.
bool cubeToViewport(double samp, double line, int &x, int &y)
Get viewport x and y from cube sample and line.
void panDown()
Pan down.
void autoStretch()
Apply automatic stretch using data from entire chip.
void geomChip(Chip *matchChip, Cube *matchChipCube)
Slot to geom chip (apply geometry transformation)
bool m_circle
Draw circle.
void changeStretchLock(int)
Locks or unlocks the stretch on the chip viewport during transformations (zoom, pan,...
void setCircleSize(int size)
Set the size of the circle.
void stretchFromCubeViewport(Stretch *, CubeViewport *)
Applies a new stretch to the specified cube viewport.
void tackPointChanged(double)
< Signal sent when tack point changes
void zoomIn()
Zoom in.
void mousePressEvent(QMouseEvent *event)
Process mouse events.
void setCross(bool checked)
Slot to change state of crosshair.
bool m_showPoints
Draw control points.
void zoom1()
Zoom by a factor of one.
BandInfo m_gray
Info for the gray bands.
QImage * m_image
The image.
void refreshView(double tackSample, double tackLine)
Slot to refresh viewport when the tack point has changed.
int m_height
Chip height.
void keyPressEvent(QKeyEvent *e)
Process arrow keystrokes on cube.
void setChip(Chip *chip, Cube *chipCube)
Set chip.
a control measurement
int GetNumPoints() const
Return the number of control points in the network.
QList< ControlMeasure * > GetMeasuresInCube(QString serialNumber)
Get all the measures pertaining to a given cube serial number.
QList< QString > GetCubeSerials() const
Use this method to get a complete list of all the cube serial numbers in the network.
@ Fixed
A Fixed point is a Control Point whose lat/lon is well established and should not be changed.
IO Handler for Isis Cubes.
Definition Cube.h:168
virtual QString fileName() const
Returns the opened cube's filename.
Definition Cube.cpp:1569
Widget to display Isis cubes for qt apps.
Container of a cube histogram.
Definition Histogram.h:74
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
This class is used to accumulate statistics on double arrays.
Definition Statistics.h:94
Pixel value mapper.
Definition Stretch.h:58
void AddPair(const double input, const double output)
Adds a stretch pair to the list of pairs.
Definition Stretch.cpp:48
void ClearPairs()
Clears the stretch pairs.
Definition Stretch.h:170
double Map(const double value) const
Maps an input value to an output value based on the stretch pairs and/or special pixel mappings.
Definition Stretch.cpp:69
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16