USGS

Isis 3.0 Object Programmers' Reference

Home

ControlPointGraphicsItem.cpp
00001 #include "ControlPointGraphicsItem.h"
00002 
00003 #include <float.h>
00004 #include <iostream>
00005 
00006 #include <QGraphicsScene>
00007 #include <QGraphicsSceneContextMenuEvent>
00008 #include <QMenu>
00009 #include <QMessageBox>
00010 
00011 #include "Constants.h"
00012 #include "ControlMeasure.h"
00013 #include "ControlPoint.h"
00014 #include "FileName.h"
00015 #include "MosaicGraphicsView.h"
00016 #include "MosaicSceneWidget.h"
00017 #include "SerialNumberList.h"
00018 #include "Statistics.h"
00019 
00020 using namespace std;
00021 
00022 namespace Isis {
00027   ControlPointGraphicsItem::ControlPointGraphicsItem(QPointF center,
00028       QPointF apriori, ControlPoint *cp, SerialNumberList *snList,
00029       MosaicSceneWidget *boundingRectSrc, QGraphicsItem *parent) :
00030       QGraphicsRectItem(parent) {
00031     m_centerPoint = new QPointF(center);
00032     m_mosaicScene = boundingRectSrc;
00033     m_controlPoint = cp;
00034     m_showArrow = false;
00035     m_colorByMeasureCount = false;
00036     m_colorByResidualMagnitude = false;
00037 
00038     m_measureCount = -1;
00039     m_residualMagnitude = Null;
00040 
00041     setZValue(DBL_MAX);
00042 
00043     m_origPoint = new QPointF(apriori);
00044 
00045     if(cp->IsIgnored())
00046       setPen(QPen(Qt::red));
00047     else if(cp->IsEditLocked())
00048       setPen(QPen(Qt::magenta));
00049     else if(cp->GetType() == ControlPoint::Fixed)
00050       setPen(QPen(Qt::green));
00051     else if(cp->GetType() == ControlPoint::Constrained)
00052       setPen(QPen(Qt::darkGreen));
00053     else // Free
00054       setPen(QPen(Qt::blue));
00055 
00056     setBrush(Qt::NoBrush);
00057 
00058     setToolTip(makeToolTip(snList));
00059 
00060     setRect(calcRect());
00061   }
00062 
00063 
00064   ControlPointGraphicsItem::~ControlPointGraphicsItem() {
00065     if(m_centerPoint) {
00066       delete m_centerPoint;
00067       m_centerPoint = NULL;
00068     }
00069 
00070     if(m_origPoint) {
00071       delete m_origPoint;
00072       m_origPoint = NULL;
00073     }
00074 
00075     m_mosaicScene = NULL;
00076   }
00077 
00078 
00079   void ControlPointGraphicsItem::paint(QPainter *painter,
00080       const QStyleOptionGraphicsItem *style,  QWidget * widget) {
00081     QRectF fullRect = calcRect();
00082     QRectF crosshairRect = calcCrosshairRect();
00083 
00084     if(crosshairRect.isNull())
00085       return;
00086 
00087     if(rect() != fullRect) {
00088       setRect(fullRect);
00089     }
00090     else {
00091       painter->setPen(pen());
00092       painter->setBrush(brush());
00093 
00094       QPointF center = crosshairRect.center();
00095 
00096       QPointF centerLeft(crosshairRect.left(), center.y());
00097       QPointF centerRight(crosshairRect.right(), center.y());
00098       QPointF centerTop(center.x(), crosshairRect.top());
00099       QPointF centerBottom(center.x(), crosshairRect.bottom());
00100 
00101       painter->drawLine(centerLeft, centerRight);
00102       painter->drawLine(centerTop, centerBottom);
00103 
00104       if(!m_origPoint->isNull() && *m_origPoint != *m_centerPoint
00105          && m_showArrow) {
00106 
00107         if (!m_colorByMeasureCount && !m_colorByResidualMagnitude) {
00108           painter->setPen(Qt::black);
00109           painter->setBrush(Qt::black);
00110         }
00111         else {
00112           QColor zeroColor(Qt::black);
00113           QColor fullColor(Qt::green);
00114 
00115           bool isColored = false;
00116 
00117           if (m_colorByMeasureCount) {
00118             int fullColorMeasureCount = qMax(1, m_measureCount);
00119             int measureCount = m_controlPoint->getMeasures(true).count();
00120             isColored = (measureCount >= fullColorMeasureCount);
00121           }
00122           else {
00123             fullColor = QColor(Qt::red);
00124 
00125             double fullColorErrorMag = 0.0;
00126 
00127             if (!IsSpecial(m_residualMagnitude)) {
00128               fullColorErrorMag = m_residualMagnitude;
00129             }
00130 
00131             Statistics residualStats;
00132             foreach (ControlMeasure *cm, m_controlPoint->getMeasures(true)) {
00133               residualStats.AddData(cm->GetResidualMagnitude());
00134             }
00135 
00136             if (residualStats.Average() != Null) {
00137               double errorMag = residualStats.Maximum();
00138               if (errorMag >= fullColorErrorMag) {
00139                 isColored = true;
00140               }
00141             }
00142           }
00143 
00144           QColor finalColor = isColored? fullColor : zeroColor;
00145 
00146           painter->setPen(finalColor);
00147           painter->setBrush(finalColor);
00148         }
00149 
00150         painter->drawLine(*m_origPoint, *m_centerPoint);
00151 
00152         QPolygonF arrowHead = calcArrowHead();
00153         painter->drawPolygon(arrowHead);
00154       }
00155     }
00156   }
00157 
00158 
00159   void ControlPointGraphicsItem::contextMenuEvent(
00160       QGraphicsSceneContextMenuEvent * event) {
00161     QMenu menu;
00162 
00163     QAction *title = menu.addAction(
00164         m_controlPoint->GetId());
00165     title->setEnabled(false);
00166     menu.addSeparator();
00167 
00168     QAction *infoAction = menu.addAction("Show Point Info");
00169 
00170     QAction *selected = menu.exec(event->screenPos());
00171 
00172     if(selected == infoAction) {
00173       QMessageBox::information(m_mosaicScene, "Control Point Information",
00174           toolTip());
00175     }
00176   }
00177 
00178 
00179   QRectF ControlPointGraphicsItem::calcRect() const {
00180     QRectF pointRect(calcCrosshairRect());
00181 
00182     if(!m_origPoint->isNull() && pointRect.isValid()) {
00183       // Make the rect contain the orig point
00184       if(pointRect.left() > m_origPoint->x()) {
00185         pointRect.setLeft(m_origPoint->x());
00186       }
00187       else if(pointRect.right() < m_origPoint->x()) {
00188         pointRect.setRight(m_origPoint->x());
00189       }
00190 
00191       if(pointRect.top() > m_origPoint->y()) {
00192         pointRect.setTop(m_origPoint->y());
00193       }
00194       else if(pointRect.bottom() < m_origPoint->y()) {
00195         pointRect.setBottom(m_origPoint->y());
00196       }
00197     }
00198 
00199     QPolygonF arrowHead = calcArrowHead();
00200 
00201     if(arrowHead.size() > 2) {
00202       pointRect = pointRect.united(arrowHead.boundingRect());
00203     }
00204 
00205     return pointRect;
00206   }
00207 
00208 
00209   QRectF ControlPointGraphicsItem::calcCrosshairRect() const {
00210     QRectF pointRect;
00211 
00212     if(m_centerPoint && !m_centerPoint->isNull() && m_mosaicScene) {
00213       static const int size = 12;
00214       QPoint findSpotScreen =
00215           m_mosaicScene->getView()->mapFromScene(*m_centerPoint);
00216       QPoint findSpotTopLeftScreen =
00217           findSpotScreen - QPoint(size / 2, size / 2);
00218 
00219       QRect pointRectScreen(findSpotTopLeftScreen, QSize(size, size));
00220 
00221       pointRect =
00222           m_mosaicScene->getView()->mapToScene(pointRectScreen).boundingRect();
00223     }
00224 
00225     return pointRect;
00226   }
00227 
00228 
00229   QPolygonF ControlPointGraphicsItem::calcArrowHead() const {
00230     QPolygonF arrowHead;
00231 
00232     if(m_showArrow && !m_origPoint->isNull() &&
00233        *m_origPoint != *m_centerPoint) {
00234       QRectF crosshairRect = calcCrosshairRect();
00235       double headSize = crosshairRect.width() * 4.0 / 5.0;
00236 
00237       double crosshairSize = headSize;
00238 
00239       // Draw arrow
00240       QPointF lineVector = *m_centerPoint - *m_origPoint;
00241       double lineVectorMag = sqrt(lineVector.x() * lineVector.x() +
00242                                   lineVector.y() * lineVector.y());
00243       double thetaPointOnLine = crosshairSize / (2 * (tanf(PI / 6) / 2) *
00244                             lineVectorMag);
00245       QPointF pointOnLine = *m_centerPoint - thetaPointOnLine * lineVector;
00246 
00247       QPointF normalVector = QPointF(-lineVector.y(), lineVector.x());
00248       double thetaNormal = crosshairSize / (2 * lineVectorMag);
00249 
00250       QPointF leftPoint = pointOnLine + thetaNormal * normalVector;
00251       QPointF rightPoint = pointOnLine - thetaNormal * normalVector;
00252 
00253       arrowHead << leftPoint << crosshairRect.center() << rightPoint;
00254     }
00255 
00256     return arrowHead;
00257   }
00258 
00259 
00260   QString ControlPointGraphicsItem::makeToolTip(SerialNumberList *snList) {
00261     QString toolTip = "<div>Point ID: " +
00262         m_controlPoint->GetId();
00263     toolTip += "<br />Point Type: " +
00264         m_controlPoint->GetPointTypeString();
00265     toolTip += "<br />Number of Measures: ";
00266     toolTip += toString(m_controlPoint->GetNumMeasures());
00267     toolTip += "<br />Ignored: ";
00268     toolTip += m_controlPoint->IsIgnored() ? "Yes" : "No";
00269     toolTip += "<br />Edit Locked: ";
00270     toolTip += m_controlPoint->IsEditLocked() ? "Yes" : "No";
00271 
00272     toolTip += "<br />";
00273 
00274     if(snList == NULL) {
00275       toolTip += QStringList(m_controlPoint->getCubeSerialNumbers()).join("\n");
00276     }
00277     else {
00278       QStringList serialNums(m_controlPoint->getCubeSerialNumbers());
00279 
00280       for(int snIndex = 0; snIndex < serialNums.size(); snIndex ++) {
00281         QString serialNum = serialNums[snIndex];
00282 
00283         if(snIndex > 0)
00284           toolTip += "<br />";
00285 
00286         if(snList->HasSerialNumber(serialNum)) {
00287           toolTip +=
00288               FileName(snList->FileName(serialNum)).name();
00289           toolTip += " (" + serialNum + ")";
00290         }
00291         else {
00292           toolTip += serialNum;
00293         }
00294 
00295         double residMag = m_controlPoint->GetMeasure(serialNum)->GetResidualMagnitude();
00296         if (residMag != Null) {
00297           toolTip += " [residual: <font color='red'>" + toString(residMag) + "</font>]";
00298         }
00299       }
00300     }
00301 
00302     toolTip += "</div>";
00303 
00304     return toolTip;
00305   }
00306 }
00307