Isis 3.0 Object Programmers' Reference |
Home |
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 }