Isis 3.0 Programmer Reference
Back | Home
ControlPointGraphicsItem.cpp
1 #include "ControlPointGraphicsItem.h"
2 
3 #include <float.h>
4 #include <iostream>
5 
6 #include <QDebug>
7 #include <QEvent>
8 #include <QGraphicsScene>
9 #include <QGraphicsSceneContextMenuEvent>
10 #include <QMenu>
11 #include <QMessageBox>
12 
13 #include "Constants.h"
14 #include "ControlMeasure.h"
15 #include "ControlPoint.h"
16 #include "FileName.h"
17 #include "MosaicGraphicsView.h"
18 #include "MosaicSceneWidget.h"
19 #include "SerialNumberList.h"
20 #include "Statistics.h"
21 
22 using namespace std;
23 
24 namespace Isis {
29  ControlPointGraphicsItem::ControlPointGraphicsItem(QPointF center,
30  QPointF apriori, ControlPoint *cp, SerialNumberList *snList,
31  MosaicSceneWidget *boundingRectSrc, QGraphicsItem *parent) :
32  QGraphicsRectItem(parent) {
33  m_centerPoint = new QPointF(center);
34  m_mosaicScene = boundingRectSrc;
35  m_controlPoint = cp;
36  m_showArrow = false;
37  m_colorByMeasureCount = false;
39 
40  m_measureCount = -1;
42 
43  setZValue(DBL_MAX);
44 
45  m_origPoint = new QPointF(apriori);
46 
47  // Providing a width of 0 makes pens cosmetic (i.e. always appear as 1 pixel on screen)
48  if (cp->IsIgnored()) {
49  setPen(QPen(Qt::red, 0.0));
50  }
51  else if (cp->IsEditLocked()) {
52  setPen(QPen(Qt::magenta, 0.0));
53  }
54  else if (cp->GetType() == ControlPoint::Fixed) {
55  setPen(QPen(Qt::green, 0.0));
56  }
57  else if (cp->GetType() == ControlPoint::Constrained) {
58  setPen(QPen(Qt::darkGreen, 0.0));
59  }
60  else {// Free
61  setPen(QPen(Qt::blue, 0.0));
62  }
63 
64  setBrush(Qt::NoBrush);
65 
66  setToolTip(makeToolTip(snList));
67 
68  setRect(calcRect());
69 
70  setFlag(QGraphicsItem::ItemIsSelectable, true);
71  setFlag(QGraphicsItem::ItemIsFocusable, true);
72 
73 // setFiltersChildEvents(true);
74 // installEventFilter(this);
75  }
76 
77 
78  ControlPointGraphicsItem::~ControlPointGraphicsItem() {
79  if (m_centerPoint) {
80  delete m_centerPoint;
81  m_centerPoint = NULL;
82  }
83 
84  if (m_origPoint) {
85  delete m_origPoint;
86  m_origPoint = NULL;
87  }
88 
89  m_mosaicScene = NULL;
90  }
91 
92 
93  void ControlPointGraphicsItem::paint(QPainter *painter,
94  const QStyleOptionGraphicsItem *style, QWidget * widget) {
95  QRectF fullRect = calcRect();
96  QRectF crosshairRect = calcCrosshairRect();
97 
98  if (crosshairRect.isNull()) {
99  return;
100  }
101 
102  if (rect() != fullRect) {
103  setRect(fullRect);
104  }
105  else {
106  painter->setPen(pen());
107  painter->setBrush(brush());
108 
109  QPointF center = crosshairRect.center();
110 
111  QPointF centerLeft(crosshairRect.left(), center.y());
112  QPointF centerRight(crosshairRect.right(), center.y());
113  QPointF centerTop(center.x(), crosshairRect.top());
114  QPointF centerBottom(center.x(), crosshairRect.bottom());
115 
116  painter->drawLine(centerLeft, centerRight);
117  painter->drawLine(centerTop, centerBottom);
118 
119  if (!m_origPoint->isNull() && *m_origPoint != *m_centerPoint
120  && m_showArrow) {
121 
123  painter->setPen(Qt::black);
124  painter->setBrush(Qt::black);
125  }
126  else {
127  QColor zeroColor(Qt::black);
128  QColor fullColor(Qt::green);
129 
130  bool isColored = false;
131 
132  if (m_colorByMeasureCount) {
133  int fullColorMeasureCount = qMax(1, m_measureCount);
134  int measureCount = m_controlPoint->getMeasures(true).count();
135  isColored = (measureCount >= fullColorMeasureCount);
136  }
137  else {
138  fullColor = QColor(Qt::red);
139 
140  double fullColorErrorMag = 0.0;
141 
143  fullColorErrorMag = m_residualMagnitude;
144  }
145 
146  Statistics residualStats;
147  foreach (ControlMeasure *cm, m_controlPoint->getMeasures(true)) {
148  residualStats.AddData(cm->GetResidualMagnitude());
149  }
150 
151  if (residualStats.Average() != Null) {
152  double errorMag = residualStats.Maximum();
153  if (errorMag >= fullColorErrorMag) {
154  isColored = true;
155  }
156  }
157  }
158 
159  QColor finalColor = isColored? fullColor : zeroColor;
160 
161  painter->setPen(finalColor);
162  painter->setBrush(finalColor);
163  }
164 
165  painter->drawLine(*m_origPoint, *m_centerPoint);
166 
167  QPolygonF arrowHead = calcArrowHead();
168  painter->drawPolygon(arrowHead);
169  }
170  }
171  }
172 
173 
174  ControlPoint *ControlPointGraphicsItem::controlPoint() {
175  return m_controlPoint;
176  }
177 
178  void ControlPointGraphicsItem::setArrowVisible(bool visible,
179  bool colorByMeasureCount,
180  int measureCount,
181  bool colorByResidualMagnitude,
182  double residualMagnitude) {
183  m_showArrow = visible;
184  m_colorByMeasureCount = colorByMeasureCount;
185  m_measureCount = measureCount;
186  m_colorByResidualMagnitude = colorByResidualMagnitude;
187  m_residualMagnitude = residualMagnitude;
188  setRect(calcRect());
189  update();
190  }
191 
192 
193  void ControlPointGraphicsItem::contextMenuEvent(
194  QGraphicsSceneContextMenuEvent * event) {
195  QMenu menu;
196 
197  QAction *title = menu.addAction(
198  m_controlPoint->GetId());
199  title->setEnabled(false);
200  menu.addSeparator();
201 
202  QAction *infoAction = menu.addAction("Show Point Info");
203 
204  QAction *selected = menu.exec(event->screenPos());
205 
206  if (selected == infoAction) {
207  QMessageBox::information(m_mosaicScene, "Control Point Information",
208  toolTip());
209  }
210  }
211 
212 
213  QRectF ControlPointGraphicsItem::calcRect() const {
214  QRectF pointRect(calcCrosshairRect());
215 
216  if (!m_origPoint->isNull() && pointRect.isValid()) {
217  // Make the rect contain the orig point
218  if (pointRect.left() > m_origPoint->x()) {
219  pointRect.setLeft(m_origPoint->x());
220  }
221  else if (pointRect.right() < m_origPoint->x()) {
222  pointRect.setRight(m_origPoint->x());
223  }
224 
225  if (pointRect.top() > m_origPoint->y()) {
226  pointRect.setTop(m_origPoint->y());
227  }
228  else if (pointRect.bottom() < m_origPoint->y()) {
229  pointRect.setBottom(m_origPoint->y());
230  }
231  }
232 
233  QPolygonF arrowHead = calcArrowHead();
234 
235  if (arrowHead.size() > 2) {
236  pointRect = pointRect.united(arrowHead.boundingRect());
237  }
238 
239  return pointRect;
240  }
241 
242 
243  QRectF ControlPointGraphicsItem::calcCrosshairRect() const {
244  QRectF pointRect;
245 
246  if (m_centerPoint && !m_centerPoint->isNull() && m_mosaicScene) {
247  static const int size = 12;
248  QPoint findSpotScreen =
249  m_mosaicScene->getView()->mapFromScene(*m_centerPoint);
250  QPoint findSpotTopLeftScreen =
251  findSpotScreen - QPoint(size / 2, size / 2);
252 
253  QRect pointRectScreen(findSpotTopLeftScreen, QSize(size, size));
254 
255  pointRect =
256  m_mosaicScene->getView()->mapToScene(pointRectScreen).boundingRect();
257  }
258 
259  return pointRect;
260  }
261 
262 
263  QPolygonF ControlPointGraphicsItem::calcArrowHead() const {
264  QPolygonF arrowHead;
265 
266  if (m_showArrow && !m_origPoint->isNull() &&
267  *m_origPoint != *m_centerPoint) {
268  QRectF crosshairRect = calcCrosshairRect();
269  double headSize = crosshairRect.width() * 4.0 / 5.0;
270 
271  double crosshairSize = headSize;
272 
273  // Draw arrow
274  QPointF lineVector = *m_centerPoint - *m_origPoint;
275  double lineVectorMag = sqrt(lineVector.x() * lineVector.x() +
276  lineVector.y() * lineVector.y());
277  double thetaPointOnLine = crosshairSize / (2 * (tanf(PI / 6) / 2) *
278  lineVectorMag);
279  QPointF pointOnLine = *m_centerPoint - thetaPointOnLine * lineVector;
280 
281  QPointF normalVector = QPointF(-lineVector.y(), lineVector.x());
282  double thetaNormal = crosshairSize / (2 * lineVectorMag);
283 
284  QPointF leftPoint = pointOnLine + thetaNormal * normalVector;
285  QPointF rightPoint = pointOnLine - thetaNormal * normalVector;
286 
287  arrowHead << leftPoint << crosshairRect.center() << rightPoint;
288  }
289 
290  return arrowHead;
291  }
292 
293 
294  QString ControlPointGraphicsItem::makeToolTip(SerialNumberList *snList) {
295  QString toolTip = "<div>Point ID: " +
296  m_controlPoint->GetId();
297  toolTip += "<br />Point Type: " +
298  m_controlPoint->GetPointTypeString();
299  toolTip += "<br />Number of Measures: ";
300  toolTip += toString(m_controlPoint->GetNumMeasures());
301  toolTip += "<br />Ignored: ";
302  toolTip += m_controlPoint->IsIgnored() ? "Yes" : "No";
303  toolTip += "<br />Edit Locked: ";
304  toolTip += m_controlPoint->IsEditLocked() ? "Yes" : "No";
305 
306  toolTip += "<br />";
307 
308  if (snList == NULL) {
309  toolTip += QStringList(m_controlPoint->getCubeSerialNumbers()).join("\n");
310  }
311  else {
312  QStringList serialNums(m_controlPoint->getCubeSerialNumbers());
313 
314  for(int snIndex = 0; snIndex < serialNums.size(); snIndex ++) {
315  QString serialNum = serialNums[snIndex];
316 
317  if (snIndex > 0) {
318  toolTip += "<br />";
319  }
320 
321  if (snList->hasSerialNumber(serialNum)) {
322  toolTip +=
323  FileName(snList->fileName(serialNum)).name();
324  toolTip += " (" + serialNum + ")";
325  }
326  else {
327  toolTip += serialNum;
328  }
329 
330  double residMag = m_controlPoint->GetMeasure(serialNum)->GetResidualMagnitude();
331  if (residMag != Null) {
332  toolTip += " [residual: <font color='red'>" + toString(residMag) + "</font>]";
333  }
334  }
335  }
336 
337  toolTip += "</div>";
338 
339  return toolTip;
340  }
341 
342 
343 //bool MosaicSceneWidget::
344 //(QObject *obj, QEvent *event) {
345 //
346 // switch(event->type()) {
347 // case QMouseEvent::GraphicsSceneMousePress: {
348 
349 
350 }
351 
PointType GetType() const
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:109
A Constrained point is a Control Point whose lat/lon/radius is somewhat established and should not be...
Definition: ControlPoint.h:361
A Fixed point is a Control Point whose lat/lon is well established and should not be changed...
Definition: ControlPoint.h:356
This widget encompasses the entire mosaic scene.
bool m_colorByMeasureCount
Are we coloring the movement arrow based on CP measure count.
double GetResidualMagnitude() const
Return Residual magnitude.
QString GetPointTypeString() const
Obtain a string representation of the PointType.
const double PI(3.14159265358979323846)
The mathematical constant PI.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
double m_residualMagnitude
Residual magnitude threshold for colored vs. black.
QString GetId() const
Return the Id of the control point.
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:199
A single control point.
Definition: ControlPoint.h:339
QList< ControlMeasure * > getMeasures(bool excludeIgnored=false) const
int m_measureCount
Measure count threshold for colored vs. black.
Serial Number list generator.
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube&#39;s serial number.
QList< QString > getCubeSerialNumbers() const
bool m_colorByResidualMagnitude
Are we coloring the movement arrow based on max CM residual magnitude.

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:16:45