1#include "ControlPointGraphicsItem.h" 
    8#include <QGraphicsScene> 
    9#include <QGraphicsSceneContextMenuEvent> 
   13#include <QPainterPath> 
   17#include "ControlMeasure.h" 
   18#include "ControlPoint.h" 
   21#include "MosaicGraphicsView.h" 
   22#include "MosaicSceneWidget.h" 
   23#include "SerialNumberList.h" 
   24#include "Statistics.h" 
   37    m_centerPoint = 
new QPointF(center);
 
   38    m_mosaicScene = boundingRectSrc;
 
   49    m_origPoint = 
new QPointF(apriori);
 
   52    if (cp->IsIgnored()) {
 
   53      setPen(QPen(Qt::yellow, 0.0));
 
   57      setPen(QPen(Qt::magenta, 0.0));
 
   60      setPen(QPen(Qt::darkGreen, 0.0));
 
   63    setBrush(Qt::NoBrush);
 
   65    setToolTip(makeToolTip(snList));
 
   69    setFlag(QGraphicsItem::ItemIsSelectable, 
true);
 
   70    setFlag(QGraphicsItem::ItemIsFocusable, 
true);
 
 
   77  ControlPointGraphicsItem::~ControlPointGraphicsItem() {
 
  100      const QStyleOptionGraphicsItem *style,  
QWidget * widget) {
 
  102    QRectF fullRect = calcRect();
 
  103    QRectF crosshairRect = calcCrosshairRect();
 
  105    if (crosshairRect.isNull()) {
 
  109    if (rect() != fullRect) {
 
  113      painter->setPen(pen());
 
  114      painter->setBrush(brush());
 
  116      QPointF center = crosshairRect.center();
 
  118      QPointF centerLeft(crosshairRect.left(), center.y());
 
  119      QPointF centerRight(crosshairRect.right(), center.y());
 
  120      QPointF centerTop(center.x(), crosshairRect.top());
 
  121      QPointF centerBottom(center.x(), crosshairRect.bottom());
 
  123      if (m_mosaicScene->directory() &&
 
  127        path.addEllipse(crosshairRect);
 
  128        path.moveTo(centerTop);
 
  129        path.lineTo(centerBottom);
 
  130        path.moveTo(centerLeft);
 
  131        path.lineTo(centerRight);
 
  133        painter->setPen(QPen(Qt::red, 0.0));
 
  134        painter->drawPath(path);
 
  137        painter->drawLine(centerLeft, centerRight);
 
  138        painter->drawLine(centerTop, centerBottom);
 
  141      if (!m_origPoint->isNull() && *m_origPoint != *m_centerPoint
 
  145          painter->setPen(Qt::black);
 
  146          painter->setBrush(Qt::black);
 
  149          QColor zeroColor(Qt::black);
 
  150          QColor fullColor(Qt::green);
 
  152          bool isColored = 
false;
 
  156            int measureCount = m_controlPoint->
getMeasures(
true).count();
 
  157            isColored = (measureCount >= fullColorMeasureCount);
 
  160            fullColor = QColor(Qt::red);
 
  162            double fullColorErrorMag = 0.0;
 
  170              residualStats.
AddData(cm->GetResidualMagnitude());
 
  173            if (residualStats.Average() != 
Null) {
 
  174              double errorMag = residualStats.Maximum();
 
  175              if (errorMag >= fullColorErrorMag) {
 
  181          QColor finalColor = isColored? fullColor : zeroColor;
 
  183          painter->setPen(finalColor);
 
  184          painter->setBrush(finalColor);
 
  186        painter->drawLine(*m_origPoint, *m_centerPoint);
 
  188        QPolygonF arrowHead = calcArrowHead();
 
  189        painter->drawPolygon(arrowHead);
 
 
  195  ControlPoint *ControlPointGraphicsItem::controlPoint() {
 
  196    return m_controlPoint;
 
  199  void ControlPointGraphicsItem::setArrowVisible(
bool visible,
 
  200                                                 bool colorByMeasureCount,
 
  202                                                 bool colorByResidualMagnitude,
 
  203                                                 double residualMagnitude) {
 
  204    m_showArrow = visible;
 
  214  void ControlPointGraphicsItem::contextMenuEvent(
 
  215      QGraphicsSceneContextMenuEvent * event) {
 
  218    QAction *title = menu.addAction(
 
  219        m_controlPoint->
GetId());
 
  220    title->setEnabled(
false);
 
  223    QAction *infoAction = menu.addAction(
"Show Point Info");
 
  225    QAction *selected = menu.exec(event->screenPos());
 
  227    if (selected == infoAction) {
 
  228      QMessageBox::information(m_mosaicScene, 
"Control Point Information",
 
  234  QRectF ControlPointGraphicsItem::calcRect()
 const {
 
  235    QRectF pointRect(calcCrosshairRect());
 
  237    if (!m_origPoint->isNull() && pointRect.isValid()) {
 
  239      if (pointRect.left() > m_origPoint->x()) {
 
  240        pointRect.setLeft(m_origPoint->x());
 
  242      else if (pointRect.right() < m_origPoint->x()) {
 
  243        pointRect.setRight(m_origPoint->x());
 
  246      if (pointRect.top() > m_origPoint->y()) {
 
  247        pointRect.setTop(m_origPoint->y());
 
  249      else if (pointRect.bottom() < m_origPoint->y()) {
 
  250        pointRect.setBottom(m_origPoint->y());
 
  254    QPolygonF arrowHead = calcArrowHead();
 
  256    if (arrowHead.size() > 2) {
 
  257      pointRect = pointRect.united(arrowHead.boundingRect());
 
  264  QRectF ControlPointGraphicsItem::calcCrosshairRect()
 const {
 
  267    if (m_centerPoint && !m_centerPoint->isNull() && m_mosaicScene) {
 
  268      static const int size = 12;
 
  269      QPoint findSpotScreen =
 
  270          m_mosaicScene->getView()->mapFromScene(*m_centerPoint);
 
  271      QPoint findSpotTopLeftScreen =
 
  272          findSpotScreen - QPoint(size / 2, size / 2);
 
  274      QRect pointRectScreen(findSpotTopLeftScreen, QSize(size, size));
 
  277          m_mosaicScene->getView()->mapToScene(pointRectScreen).boundingRect();
 
  284  QPolygonF ControlPointGraphicsItem::calcArrowHead()
 const {
 
  287    if (m_showArrow && !m_origPoint->isNull() &&
 
  288       *m_origPoint != *m_centerPoint) {
 
  289      QRectF crosshairRect = calcCrosshairRect();
 
  290      double headSize = crosshairRect.width() * 4.0 / 5.0;
 
  292      double crosshairSize = headSize;
 
  295      QPointF lineVector = *m_centerPoint - *m_origPoint;
 
  296      double lineVectorMag = sqrt(lineVector.x() * lineVector.x() +
 
  297                                  lineVector.y() * lineVector.y());
 
  298      double thetaPointOnLine = crosshairSize / (2 * (tanf(
PI / 6) / 2) *
 
  300      QPointF pointOnLine = *m_centerPoint - thetaPointOnLine * lineVector;
 
  302      QPointF normalVector = QPointF(-lineVector.y(), lineVector.x());
 
  303      double thetaNormal = crosshairSize / (2 * lineVectorMag);
 
  305      QPointF leftPoint = pointOnLine + thetaNormal * normalVector;
 
  306      QPointF rightPoint = pointOnLine - thetaNormal * normalVector;
 
  308      arrowHead << leftPoint << crosshairRect.center() << rightPoint;
 
  315  QString ControlPointGraphicsItem::makeToolTip(SerialNumberList *snList) {
 
  316    QString toolTip = 
"<div>Point ID: " +
 
  317        m_controlPoint->
GetId();
 
  318    toolTip += 
"<br />Point Type: " +
 
  320    toolTip += 
"<br />Number of Measures: ";
 
  321    toolTip += 
toString(m_controlPoint->GetNumMeasures());
 
  322    toolTip += 
"<br />Ignored: ";
 
  323    toolTip += m_controlPoint->IsIgnored() ? 
"Yes" : 
"No";
 
  324    toolTip += 
"<br />Edit Locked: ";
 
  325    toolTip += m_controlPoint->IsEditLocked() ? 
"Yes" : 
"No";
 
  329    if (snList == NULL) {
 
  335      for(
int snIndex = 0; snIndex < serialNums.size(); snIndex ++) {
 
  336        QString serialNum = serialNums[snIndex];
 
  342        if (snList->hasSerialNumber(serialNum)) {
 
  344              FileName(snList->fileName(serialNum)).name();
 
  345          toolTip += 
" (" + serialNum + 
")";
 
  348          toolTip += serialNum;
 
  351        double residMag = m_controlPoint->
GetMeasure(serialNum)->GetResidualMagnitude();
 
  352        if (residMag != 
Null) {
 
  353          toolTip += 
" [residual: <font color='red'>" + 
toString(residMag) + 
"</font>]";
 
bool m_colorByResidualMagnitude
Are we coloring the movement arrow based on max CM residual magnitude.
 
int m_measureCount
Measure count threshold for colored vs. black.
 
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *widget=0)
This virtual paint method is called anytime an update() or paintEvent() is called.
 
ControlPointGraphicsItem(QPointF center, QPointF apriori, ControlPoint *cp, SerialNumberList *snList, MosaicSceneWidget *scene, QGraphicsItem *parent)
Create a CP graphics item.
 
double m_residualMagnitude
Residual magnitude threshold for colored vs. black.
 
bool m_colorByMeasureCount
Are we coloring the movement arrow based on CP measure count.
 
QList< QString > getCubeSerialNumbers() const
 
@ Constrained
A Constrained point is a Control Point whose lat/lon/radius is somewhat established and should not be...
 
@ Fixed
A Fixed point is a Control Point whose lat/lon is well established and should not be changed.
 
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube's serial number.
 
QString GetPointTypeString() const
Obtain a string representation of the PointType.
 
QString GetId() const
Return the Id of the control point.
 
QList< ControlMeasure * > getMeasures(bool excludeIgnored=false) const
 
QString editPointId()
Return the current control point id loaded in the ControlPointEditWidget.
 
Serial Number list generator.
 
This class is used to accumulate statistics on double arrays.
 
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
 
This is free and unencumbered software released into the public domain.
 
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
 
const double Null
Value for an Isis Null pixel.
 
bool IsSpecial(const double d)
Returns if the input pixel is special.
 
const double PI
The mathematical constant PI.
 
Namespace for the standard library.