USGS

Isis 3.0 Object Programmers' Reference

Home

ChipViewport.cpp
00001 #include "IsisDebug.h"
00002 
00003 #include "ChipViewport.h"
00004 
00005 #include <iostream>
00006 
00007 #include <QMessageBox>
00008 #include <QPainter>
00009 
00010 #include "ControlMeasure.h"
00011 #include "ControlNet.h"
00012 #include "ControlPoint.h"
00013 #include "Cube.h"
00014 #include "CubeViewport.h"
00015 #include "SerialNumber.h"
00016 #include "Stretch.h"
00017 
00018 namespace Isis {
00019 
00021   ChipViewport::ChipViewport(int width, int height, QWidget *parent) :
00022     QWidget(parent) {
00023 
00024     setFixedSize(width, height);
00025     setBackgroundRole(QPalette::Dark);
00026 //    setFocusPolicy(Qt::StrongFocus);
00027 
00028     p_width = width;
00029     p_height = height;
00030     p_zoomFactor = 1.0;
00031     p_rotation = 0;
00032     p_geomIt = false;
00033     p_tempView = NULL;
00034     p_cross = true;
00035     p_circle = false;
00036     p_chip = NULL;
00037     p_chipCube = NULL;
00038     p_matchChip = NULL;
00039     p_matchChipCube = NULL;
00040     p_image = NULL;
00041     p_controlNet = NULL;
00042     p_stretchLocked = false;
00043     p_stretch = NULL;
00044 
00045     p_stretch = new Stretch;
00046   }
00047 
00048 
00053   ChipViewport::~ChipViewport() {
00054     if (p_stretch) {
00055       delete p_stretch;
00056       p_stretch = NULL;
00057     }
00058   }
00059 
00060 
00071   bool ChipViewport::cubeToViewport(double samp, double line,
00072                                     int &x, int &y) {
00073 
00074     p_chip->SetCubePosition(samp, line);
00075     x = ((int) p_chip->ChipSample()) - 1;
00076     y = ((int) p_chip->ChipLine()) - 1;
00077 
00078     return p_chip->IsInsideChip(samp, line);
00079   }
00080 
00081 
00091   void ChipViewport::setChip(Chip *chip, Cube *chipCube) {
00092     // Is the chip usable?
00093     if (chip == NULL || chipCube == NULL) {
00094       throw IException(IException::Programmer,
00095                        "Can not view NULL chip pointer",
00096                        _FILEINFO_);
00097     }
00098 
00099     p_zoomFactor = 1.0;
00100     p_rotation = 0;
00101 
00102     p_chip = chip;
00103     p_chipCube = chipCube;
00104     if (p_image != NULL)
00105       delete p_image;
00106     p_image = new QImage(chip->Samples(), chip->Lines(), QImage::Format_RGB32);
00107 
00108     autoStretch();
00109     emit tackPointChanged(p_zoomFactor);
00110   }
00111 
00112 
00114   void ChipViewport::autoStretch() {
00115     computeStretch(p_gray.stretch);
00116     paintImage();
00117     update();
00118   }
00119 
00120 
00121   void ChipViewport::stretchFromCubeViewport(Stretch *newStretch,
00122       CubeViewport *cvp) {
00123 
00124     ASSERT(cvp != NULL);
00125 
00126     if (!cvp || !p_chipCube)
00127       return;
00128 
00129     // only stretch if the CubeViewport is opened to the same cube as we are,
00130     // otherwise the signal was meant for a different ChipViewport!
00131     if (cvp->cube()->fileName() == p_chipCube->fileName()) {
00132 
00133       // if user right clicked in the CubeViewport then we get a SIGNAL with a
00134       // NULL Stretch.  This is used to signify that we need to restretch on our
00135       // own (go back to global).
00136       if (!newStretch) {
00137         computeStretch(p_gray.stretch, true);
00138         paintImage();
00139         update();
00140       }
00141       else {
00142         *p_stretch = *newStretch;
00143         p_gray.stretch = *newStretch;
00144         paintImage();
00145         update();
00146       }
00147     }
00148   }
00149 
00150 
00151   void ChipViewport::changeStretchLock(int newStatus) {
00152     if (newStatus == 0)
00153       p_stretchLocked = false;
00154     else
00155       p_stretchLocked = true;
00156   }
00157 
00158 
00160   void ChipViewport::computeStretch(Stretch &stretch, bool force) {
00161     if (p_stretchLocked && !force) {
00162       stretch = *p_stretch;
00163     }
00164     else {
00165       Statistics stats;
00166       for (int line = 1; line < p_chip->Lines(); line++) {
00167         for (int samp = 1; samp < p_chip->Samples(); samp++) {
00168           double value = p_chip->GetValue(samp, line);
00169           stats.AddData(&value, 1);
00170         }
00171       }
00172 
00173       Histogram hist(stats.BestMinimum(), stats.BestMaximum());
00174       for (int line = 1; line <= p_chip->Lines(); line++) {
00175         for (int samp = 1; samp <= p_chip->Samples(); samp++) {
00176           double value = p_chip->GetValue(samp, line);
00177           hist.AddData(&value, 1);
00178         }
00179       }
00180 
00181       stretch.ClearPairs();
00182       if (hist.Percent(0.5) != hist.Percent(99.5)) {
00183         stretch.AddPair(hist.Percent(0.5), 0.0);
00184         stretch.AddPair(hist.Percent(99.5), 255.0);
00185       }
00186       else {
00187         stretch.AddPair(-DBL_MAX, 0.0);
00188         stretch.AddPair(DBL_MAX, 255.0);
00189       }
00190 
00191       *p_stretch = stretch;
00192     }
00193   }
00194 
00195 
00197   void ChipViewport::paintImage() {
00198     //  TODO: ??? Need something similar to CubeViewport clipping, so that
00199     //         at edge of image, fill viewport w/ black
00200     for (int y = 0; y < p_chip->Lines(); y++) {
00201       QRgb *rgb = (QRgb *) p_image->scanLine(y);
00202       int r, g, b;
00203       for (int x = 0; x < p_chip->Samples(); x++) {
00204         r = g = b = (int) p_gray.stretch.Map(p_chip->GetValue(x + 1, y + 1));
00205         rgb[x] =  qRgb(r, g, b);
00206       }
00207     }
00208     repaint();
00209 
00210   }
00211 
00212 
00213 
00224   void ChipViewport::paintEvent(QPaintEvent *e) {
00225     QPainter painter(this);
00226 
00227     if (p_tempView != NULL) {
00228       painter.drawImage(0, 0, *(p_tempView->p_image));
00229     }
00230     else {
00231       painter.drawImage(0, 0, *p_image);
00232     }
00233 
00234     if (p_cross == true) {
00235       painter.setPen(Qt::red);
00236       painter.drawLine(0, (p_height - 1) / 2, p_width - 1, (p_height - 1) / 2);
00237       painter.drawLine((p_width - 1) / 2, 0, (p_width - 1) / 2, p_height - 1);
00238     }
00239 
00240     if (p_circle == true) {
00241       painter.setPen(Qt::red);
00242       painter.drawEllipse((p_height - 1) / 2 - p_circleSize / 2,
00243                           (p_width - 1) / 2 - p_circleSize / 2,
00244                           p_circleSize, p_circleSize);
00245     }
00246 
00247     QString serialNumber = SerialNumber::Compose(*p_chipCube);
00248     if (p_controlNet && p_controlNet->GetCubeSerials().contains(
00249                              serialNumber)) {
00250       // draw measure locations if we have a control network
00251       //  If the serial number is Unknown, we probably have a ground source
00252       //  file or level 2 which means it does not exist in the network
00253       //  TODO:  Is there a better way to handle this?
00254       if (p_showPoints && serialNumber.compare("Unknown") &&
00255           p_controlNet->GetNumPoints() != 0) {
00256         QList<ControlMeasure *> measures =
00257                                    p_controlNet->GetMeasuresInCube(serialNumber);
00258         // loop through all points in the control net
00259         for (int i = 0; i < measures.count(); i++) {
00260           ControlMeasure *m = measures[i];
00261           // Find the measurments on the viewport
00262           double samp = m->GetSample();
00263           double line = m->GetLine();
00264           int x, y;
00265 
00266           cubeToViewport(samp, line, x, y);
00267           // Determine pen color
00268           // if the point or measure is ignored set to yellow
00269           if (m->Parent()->IsIgnored() ||
00270              (!m->Parent()->IsIgnored() && m->IsIgnored())) {
00271             painter.setPen(QColor(255, 255, 0)); // set point marker yellow
00272           }
00273           // check for ground measure
00274           else if (m->Parent()->GetType() == ControlPoint::Fixed) {
00275             painter.setPen(Qt::magenta);// set point marker magenta
00276           }
00277           else {
00278             painter.setPen(Qt::green); // set all other point markers green
00279           }
00280 
00281           // draw points which are not under cross
00282           if (x != (p_width - 1) / 2 || y != (p_height - 1) / 2) {
00283             painter.drawLine(x - 5, y, x + 5, y);
00284             painter.drawLine(x, y - 5, x, y + 5);
00285           }
00286         }
00287       }
00288     }
00289 
00290     p_tempView = NULL;
00291     //painter.end();
00292 
00293   }
00294 
00295 
00297   void ChipViewport::loadView(ChipViewport &newView) {
00298     p_tempView = &newView;
00299     update();
00300   }
00301 
00302 
00309   double ChipViewport::tackSample() {
00310     p_chip->SetChipPosition(p_chip->TackSample(), p_chip->TackLine());
00311     return p_chip->CubeSample();
00312   }
00313 
00314 
00321   double ChipViewport::tackLine() {
00322     p_chip->SetChipPosition(p_chip->TackSample(), p_chip->TackLine());
00323     return p_chip->CubeLine();
00324   }
00325 
00326 
00328   void ChipViewport::panUp() {
00329     int x, y;
00330     x = p_chip->TackSample();
00331     y = p_chip->TackLine() - 1;
00332     //  Reload with new cube position
00333     p_chip->SetChipPosition((double)x, (double)y);
00334     reloadChip(p_chip->CubeSample(), p_chip->CubeLine());
00335   }
00336 
00337 
00339   void ChipViewport::panDown() {
00340     int x, y;
00341     x = p_chip->TackSample();
00342     y = p_chip->TackLine() + 1;
00343     //  Reload with new cube position
00344     p_chip->SetChipPosition((double)x, (double)y);
00345     reloadChip(p_chip->CubeSample(), p_chip->CubeLine());
00346   }
00347 
00348 
00350   void ChipViewport::panLeft() {
00351     int x, y;
00352     x = p_chip->TackSample() - 1;
00353     y = p_chip->TackLine();
00354     //  Reload with new cube position
00355     p_chip->SetChipPosition((double)x, (double)y);
00356     reloadChip(p_chip->CubeSample(), p_chip->CubeLine());
00357   }
00358 
00359 
00361   void ChipViewport::panRight() {
00362     int x, y;
00363     x = p_chip->TackSample() + 1;
00364     y = p_chip->TackLine();
00365     //  Reload with new cube position
00366     p_chip->SetChipPosition((double)x, (double)y);
00367     reloadChip(p_chip->CubeSample(), p_chip->CubeLine());
00368   }
00369 
00370 
00375   void ChipViewport::zoomIn() {
00376 
00377     p_zoomFactor /= 2.0;
00378     reloadChip();
00379   }
00380 
00381 
00386   void ChipViewport::zoomOut() {
00387 
00388     p_zoomFactor *= 2.0;
00389     reloadChip();
00390   }
00391 
00392 
00397   void ChipViewport::zoom1() {
00398 
00399     p_zoomFactor = 1.0;
00400     reloadChip();
00401   }
00402 
00403 
00404   void ChipViewport::zoom(double zoomFactor) {
00405     p_zoomFactor = zoomFactor;
00406     reloadChip();
00407   }
00408 
00409 
00410 
00411   double ChipViewport::zoomFactor() {
00412     return p_zoomFactor;
00413   }
00414 
00415 
00416 
00418   void ChipViewport::refreshView(double tackSample, double tackLine) {
00419 
00420     reloadChip(tackSample, tackLine);
00421 
00422   }
00423 
00424 
00426   void ChipViewport::enterEvent(QEvent *e) {
00427     setFocus();
00428   }
00429 
00430 
00432   void ChipViewport::keyPressEvent(QKeyEvent *e) {
00433 
00434     int x, y;
00435     x = p_chip->TackSample();
00436     y = p_chip->TackLine();
00437     if (e->key() == Qt::Key_Up) {
00438       y--;
00439     }
00440     else if (e->key() == Qt::Key_Down) {
00441       y++;
00442     }
00443     else if (e->key() == Qt::Key_Left) {
00444       x--;
00445     }
00446     else if (e->key() == Qt::Key_Right) {
00447       x++;
00448     }
00449     else {
00450       QWidget::keyPressEvent(e);
00451       return;
00452     }
00453 
00454     //  Reload with new cube position
00455     p_chip->SetChipPosition((double)x, (double)y);
00456     reloadChip(p_chip->CubeSample(), p_chip->CubeLine());
00457     emit userMovedTackPoint();
00458   }
00459 
00460 
00461 
00469   void ChipViewport::mousePressEvent(QMouseEvent *event) {
00470 
00471     QPoint p = event->pos();
00472     if (event->button() == Qt::LeftButton) {
00473       //  Reload with new cube position
00474       p_chip->SetChipPosition((double)p.x(), (double)p.y());
00475       reloadChip(p_chip->CubeSample(), p_chip->CubeLine());
00476       emit userMovedTackPoint();
00477       //  This was added when the scrolled area was added to the QnetTool.
00478       //  For some reason when clicking in the ChipViewport, focus would be
00479       //  lost and the arrow keys would no longer work.
00480       //  TODO:  Is this the correct way to fix this, why is it happening?
00481       setFocus();
00482     }
00483   }
00484 
00485 
00487   void ChipViewport::setPoints(bool checked) {
00488 
00489     if (checked == p_showPoints)
00490       return;
00491 
00492     p_showPoints = checked;
00493     repaint();
00494 
00495   }
00496 
00497 
00499   void ChipViewport::setCross(bool checked) {
00500 
00501     if (checked == p_cross)
00502       return;
00503 
00504     p_cross = checked;
00505     repaint();
00506 
00507   }
00508 
00509 
00510   void ChipViewport::setCircle(bool checked) {
00511 
00512     if (checked == p_circle)
00513       return;
00514 
00515     p_circle = checked;
00516     repaint();
00517   }
00518 
00519 
00520   void ChipViewport::setCircleSize(int size) {
00521 
00522     p_circleSize = size;
00523     repaint();
00524 
00525   }
00526 
00527 
00528 
00535   void ChipViewport::geomChip(Chip *matchChip, Cube *matchChipCube) {
00536 
00537     p_geomIt = true;
00538     p_matchChip = matchChip;
00539     p_matchChipCube = matchChipCube;
00540     try {
00541       p_chip->Load(*p_chipCube, *matchChip, *matchChipCube);
00542 //    p_chip->ReLoad(*matchChip,p_zoomFactor);
00543     }
00544     catch (IException &e) {
00545       QString msg = "Cannot geom chip.\n";
00546       msg += e.toString();
00547       QMessageBox::information((QWidget *)parent(), "Error", msg);
00548       return;
00549     }
00550 
00551     //  TODO:   ??? Can these be added to paintEvent method ???
00552     autoStretch();
00553   }
00554 
00561   void ChipViewport::nogeomChip() {
00562 
00563     p_geomIt = false;
00564     try {
00565       p_chip->Load(*p_chipCube, p_rotation, p_zoomFactor);
00566     }
00567     catch (IException &e) {
00568       QString msg = "Cannot load no geom chip.\n";
00569       msg += e.toString();
00570       QMessageBox::information((QWidget *)parent(), "Error", msg);
00571       return;
00572     }
00573 
00574     //  TODO:   ??? Can these be added to paintEvent method ???
00575     autoStretch();
00576   }
00577 
00578 
00590   void ChipViewport::rotateChip(int rotation) {
00591 
00592     p_rotation = -rotation;
00593     try {
00594       p_chip->Load(*p_chipCube, -rotation, p_zoomFactor);
00595     }
00596     catch (IException &e) {
00597       QString msg = "Cannot load rotated chip.\n";
00598       msg += e.toString();
00599       QMessageBox::information((QWidget *)parent(), "Error", msg);
00600       return;
00601     }
00602 
00603     //  TODO:   ??? Can these be added to paintEvent method ???
00604     autoStretch();
00605   }
00606 
00607 
00617   void ChipViewport::reloadChip(double tackSample, double tackLine) {
00618 
00619     // Is the chip usable?
00620     if (p_chip == NULL) {
00621       throw IException(IException::Programmer,
00622                        "Can not view NULL chip pointer",
00623                        _FILEINFO_);
00624     }
00625 
00626     if (tackSample != 0. && tackLine != 0.)
00627       p_chip->TackCube(tackSample, tackLine);
00628     if (p_geomIt) {
00629       if (p_matchChip == NULL) {
00630         throw IException(IException::User, "Invalid match chip", _FILEINFO_);
00631       }
00632       try {
00633         p_chip->Load(*p_chipCube, *p_matchChip, *p_matchChipCube);
00634       }
00635       catch (IException &e) {
00636         QString msg = "Cannot reload chip.\n";
00637         msg += e.toString();
00638         QMessageBox::information((QWidget *)parent(), "Error", msg);
00639         return;
00640       }
00641 //      p_chip->ReLoad(*p_matchChip,p_zoomFactor);
00642     }
00643     else {
00644       try {
00645         p_chip->Load(*p_chipCube, p_rotation, p_zoomFactor);
00646       }
00647       catch (IException &e) {
00648         QString msg = "Cannot reload chip.\n";
00649         msg += e.toString();
00650         QMessageBox::information((QWidget *)parent(), "Error", msg);
00651         return;
00652       }
00653     }
00654 
00655 
00656     //  TODO:   ??? Can these be added to paintEvent method ???
00657     autoStretch();
00658 
00659     //  emit signal indicating tack point changed so that the TieTool
00660     //  can update the sample/line label.
00661     emit tackPointChanged(p_zoomFactor);
00662   }
00663 }