Isis 3 Programmer Reference
MatrixSceneWidget.cpp
1 #include "IsisDebug.h"
2 
3 #include "MatrixSceneWidget.h"
4 
5 #include <float.h>
6 #include <sstream>
7 
8 #include <QGraphicsRectItem>
9 #include <QGraphicsSceneMouseEvent>
10 #include <QList>
11 #include <QMap>
12 #include <QPen>
13 #include <QtCore>
14 #include <QtWidgets>
15 #include <QtXml>
16 #include <QTransform>
17 
18 #include "CorrelationMatrix.h"
19 #include "Directory.h"
20 #include "Distance.h"
21 #include "FileName.h"
22 #include "GraphicsView.h"
23 #include "IException.h"
24 #include "IString.h"
25 #include "MatrixGraphicsScene.h"
26 #include "MatrixGraphicsView.h"
27 #include "MatrixOptions.h"
28 #include "ProgressBar.h"
29 #include "Project.h"
30 #include "PvlObject.h"
31 #include "Pvl.h"
32 #include "SparseBlockMatrix.h"
33 #include "TextFile.h"
34 #include "Target.h"
35 #include "ToolPad.h"
36 #include "XmlStackedHandlerReader.h"
37 
38 #include <boost/numeric/ublas/fwd.hpp>
39 #include <boost/numeric/ublas/io.hpp>
40 #include <boost/numeric/ublas/matrix_sparse.hpp>
41 #include <boost/numeric/ublas/matrix_proxy.hpp>
42 
43 using namespace boost::numeric::ublas;
44 namespace Isis {
54  MatrixSceneWidget::MatrixSceneWidget(QStatusBar *status,
55  bool showTools,
56  bool internalizeToolBarsAndProgress,
57  Directory *directory,
58  QWidget *parent) : QWidget(parent) {
60 
62  m_graphicsScene->installEventFilter(this);
63 
66  m_graphicsView->setInteractive(true);
67 
68 // try {
69 // m_matrixOptions = new MatrixOptions(
70 // m_directory->project()->lastNotUndoneWorkOrder()->correlationMatrix(), this);
71 // connect(m_matrixOptions, SIGNAL( optionsUpdated() ),
72 // this, SLOT( redrawElements() ) );
73 // }
74 // catch (IException &e) {
75 // throw IException(e, IException::Unknown, "bad workorder", _FILEINFO_);
76 // }
77 
78  // Draw Initial Matrix
79 // try {
80 // drawElements( m_directory->project()->lastNotUndoneWorkOrder()->correlationMatrix() );
81 // drawGrid( m_directory->project()->lastNotUndoneWorkOrder()->correlationMatrix() );
82 // }
83 // catch (IException &e) {
84 // throw IException(e, IException::Unknown, "bad workorder", _FILEINFO_);
85 // }
86 
87  m_graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);
88 
89  m_quickMapAction = NULL;
90 
91  m_outlineRect = NULL;
92 
93  m_progress = new ProgressBar;
94  m_progress->setVisible(false);
95 
96  QGridLayout * sceneLayout = new QGridLayout;
97  sceneLayout->setContentsMargins(0, 0, 0, 0);
98  setLayout(sceneLayout);
99 
100  // If we are making our own layout, we can create our own status area.
101  if (!status && internalizeToolBarsAndProgress)
102  status = new QStatusBar;
103 
104  if (showTools) {
105 
106  if (internalizeToolBarsAndProgress) {
107 
108  sceneLayout->addWidget(m_graphicsView, 1, 1, 1, 1);
109 
110  QHBoxLayout *horizontalStatusLayout = new QHBoxLayout;
111  horizontalStatusLayout->addWidget(m_progress);
112  horizontalStatusLayout->addStretch();
113  horizontalStatusLayout->addWidget(status);
114 
115  sceneLayout->addLayout(horizontalStatusLayout, 2, 0, 1, 2);
116  }
117  else {
118  sceneLayout->addWidget(m_graphicsView, 0, 0, 1, 1);
119  }
120 
121  setWhatsThis("This is the matrix scene. You can interact with the "
122  "matrix elements shown here. ");
123 
124  getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
125  getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
126 
127  getView()->enableResizeZooming(false);
128 
129  connect( getView()->horizontalScrollBar(), SIGNAL( valueChanged(int) ),
130  this, SLOT( sendVisibleRectChanged() ) );
131  connect( getView()->verticalScrollBar() , SIGNAL( valueChanged(int) ),
132  this, SLOT( sendVisibleRectChanged() ) );
133  connect( getView()->horizontalScrollBar(), SIGNAL( rangeChanged(int, int) ),
134  this, SLOT( sendVisibleRectChanged() ) );
135  connect( getView()->verticalScrollBar() , SIGNAL( rangeChanged(int, int) ),
136  this, SLOT( sendVisibleRectChanged() ) );
137  }
138  else {
139  sceneLayout->addWidget(m_graphicsView, 0, 0, 1, 1);
140 
141  getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
142  getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
143 
144  setWhatsThis("This is the matrix world view. The matrix will be "
145  "shown here, but you cannot zoom in.");
146  }
147 // draw elements
148  }
149 
150 
155  m_outlineRect = NULL; // The scene will clean this up
156  }
157 
158 
165  return m_graphicsView;
166  }
167 
168 
175  return m_graphicsScene;
176  }
177 
178 
186  bool MatrixSceneWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
187  bool handled = false;
188 
189  QList<QGraphicsItem *> selectedGraphicsItems = getScene()->selectedItems();
190  // qDebug() << "number of selected items:" << selectedGraphicsItems.count();
191 // QList<MatrixSceneItem *> selectedMatrixElementItems;
192 // QList<MatrixElement*> selectedMatrixElements;
193 //
194 // foreach (QGraphicsItem *graphicsItem, selectedGraphicsItems) {
195 // MatrixSceneItem *sceneMatrixElementItem = dynamic_cast<MatrixSceneItem *>(graphicsItem);
196 //
197 // if (!sceneMatrixElementItem) {
198 // sceneMatrixElementItem = dynamic_cast<MatrixSceneItem *>( graphicsItem->parentItem() );
199 // }
200 //
201 // if ( sceneMatrixElementItem && sceneMatrixElementItem->element() ) {
202 // selectedMatrixElementItems.append(sceneMatrixElementItem);
203 // selectedMatrixElements.append( sceneMatrixElementItem->element() );
204 // }
205 // }
206 //
207 // if ( selectedMatrixElementItems.count() ) {
208 // QMenu menu;
209 //
210 // QAction *title = menu.addAction( tr("%L1 Selected MatrixElements").arg( selectedMatrixElements.count() ) );
211 // title->setEnabled(false);
212 // menu.addSeparator();
213 //
214 // Project *project = m_directory ? m_directory->project() : NULL;
215 //
216 // QList<QAction *> displayActs = selectedMatrixElements.supportedActions(project);
217 //
218 // if (m_directory) {
219 // displayActs.append(NULL);
220 // displayActs.append( m_directory->supportedActions( new QList<MatrixElement*>(selectedMatrixElements) ) );
221 // }
222 //
223 // QAction *displayAct;
224 // foreach(displayAct, displayActs) {
225 // if (displayAct == NULL) {
226 // menu.addSeparator();
227 // }
228 // else {
229 // menu.addAction(displayAct);
230 // }
231 // }
232 //
233 // handled = true;
234 // menu.exec( event->screenPos() );
235 // }
236 
237  return handled;
238  }
239 
240 
247  return m_progress;
248  }
249 
250 
251 
252 // void MatrixSceneWidget::load(XmlStackedHandlerReader *xmlReader) {
253 // xmlReader->pushContentHandler( new XmlHandler(this) );
254 // }
255 
256 
263  QRectF boundingRect;
264 
265  if (m_outlineRect)
266  boundingRect = boundingRect.united( m_outlineRect->boundingRect() );
267 
268  return boundingRect;
269  }
270 
271 
278  return m_directory;
279  }
280 
281 
288  QList<QAction *> viewActs;
289 
290 // foreach(MatrixTool *tool, *m_tools) {
291 // QList<QAction *> toolViewActs = tool->getViewActions();
292 // viewActs.append(toolViewActs);
293 // }
294 
295  return viewActs;
296  }
297 
298 
306  QList<QAction *> results;
307 
308  return results;
309  }
310 
311 
316 // void MatrixSceneWidget::refit() {
317 // QRectF sceneRect = m_graphicsScene->itemsBoundingRect();
318 //
319 // if ( sceneRect.isEmpty() )
320 // return;
321 //
322 // // double xPadding = sceneRect.width() * 0.10;
323 // // double yPadding = sceneRect.height() * 0.10;
324 // //
325 // // sceneRect.adjust(-xPadding, -yPadding, xPadding, yPadding);
326 // getView()->fitInView(sceneRect, Qt::KeepAspectRatio);
327 // }
328 
329 
334  QPointF topLeft = getView()->mapToScene(0, 0);
335  QPointF bottomRight =
336  getView()->mapToScene( (int)getView()->width(), (int)getView()->height() );
337 
338  QRectF visibleRect(topLeft, bottomRight);
339  emit visibleRectChanged(visibleRect);
340  }
341 
342 
360  bool MatrixSceneWidget::eventFilter(QObject *obj, QEvent *event) {
361  bool stopProcessingEvent = true;
362 
363  switch( event->type() ) {
364  case QMouseEvent::GraphicsSceneMousePress: {
365  if (m_graphicsScene->itemAt( ( (QGraphicsSceneMouseEvent *)event )->scenePos(),
366  QTransform() ) ) {
367  emit elementClicked(m_graphicsScene->itemAt(
368  ( (QGraphicsSceneMouseEvent *)event )->scenePos(),
369  QTransform() )->toolTip() );
370  }
371  stopProcessingEvent = false;
372  break;
373  }
374 
375  case QMouseEvent::GraphicsSceneMouseDoubleClick:
376  emit mouseDoubleClick(
377  ((QGraphicsSceneMouseEvent *)event)->scenePos());
378  m_graphicsView->fitInView(m_graphicsScene->itemsBoundingRect(), Qt::KeepAspectRatio);
379  stopProcessingEvent = false;
380  break;
381 
382  default:
383  stopProcessingEvent = false;
384  break;
385  }
386 
387  return stopProcessingEvent;
388  }
389 
390 
396  }
397 
398 
399 // /**
400 // * Refit scene and items when the widget size changes.
401 // */
402 // void MatrixSceneWidget::fitInView() {
403 // }
404 
405 
416  int elementSize = 10;
417  int startX = 20;
418  int x = 20;
419  int startY = 20;
420  int y = 20;
421  int yOffset = 0;
423  QGraphicsRectItem *rectangle;
424  QList<int> paramList;
425 
426  // This will change depending on the values of the elements
427  QBrush fillBrush(Qt::blue);
428  QPen outlinePen(Qt::black);
429  outlinePen.setWidth(0);
430 
431  // Image and parameters of column
432  QMapIterator<QString, QStringList> colIterator( *corrMatrix.imagesAndParameters() );
433  // Image and parameters of row
434  QMapIterator<QString, QStringList> rowIterator( *corrMatrix.imagesAndParameters() );
435 
436  foreach ( SparseBlockColumnMatrix blockColumn, *( corrMatrix.visibleBlocks() ) ) {
437  QMapIterator<int, matrix<double>*> block(blockColumn);
438  bool lastBlock = true;
439  block.toBack(); // moves iterator to AFTER the last item
440  colIterator.next();
441  rowIterator = colIterator;
442 
443  do {
444  block.previous(); // go to last item
445  rowIterator.previous();
446  for (int row = 0; row < (int)block.value()->size1(); row++) {
447  for (int column = 0; column < (int)block.value()->size2(); column++) {
448 
449  // The values of this matrix should always be between 1 and -1.
450  QColor fillColor;
451  if ( !m_matrixOptions->colorScheme() ) {
452  double red = 0;
453  double green = 0;
454  double lowerColorValue = fabs( ( *block.value() )(row, column) ) * 255.0;
455  if (fabs( ( *block.value() )(row, column) ) < .5) {
456  red = lowerColorValue * 2;
457  green = 255;
458  }
459  else {
460  green = 255 - ( (lowerColorValue - 127.5) * 2 );
461  red = 255;
462  }
463  fillColor = QColor(red, green, 0);
464  }
465 
466  bool draw = true;
467  // Deal with diagonal.
468  if (lastBlock) {
469  if (column < row) {
470  draw = false;
471  }
472  else if (column == row) {
473  outlinePen.setColor(Qt::black);
474  fillBrush.setColor(Qt::blue); // This will always be a single color
475  }
476  else {
477  outlinePen.setColor(Qt::black);
478  if ( m_matrixOptions->colorScheme() ) {
479  if ( fabs( ( *block.value() )(row, column) ) >=
481  fillBrush.setColor( m_matrixOptions->badCorrelationColor() );
482  }
483  else {
484  fillBrush.setColor( m_matrixOptions->goodCorrelationColor() );
485  }
486  }
487  else {
488  fillBrush.setColor(fillColor);
489  }
490  }
491  }
492  else {
493  outlinePen.setColor(Qt::black);
494  if ( m_matrixOptions->colorScheme() ) {
495  if ( fabs( ( *block.value() )(row, column) ) >=
497  fillBrush.setColor( m_matrixOptions->badCorrelationColor() );
498  }
499  else {
500  fillBrush.setColor( m_matrixOptions->goodCorrelationColor() );
501  }
502  }
503  else {
504  fillBrush.setColor(fillColor);
505  }
506  }
507 
508  // Should rectangle be a matrix element?
509  if (draw) {
510  rectangle = m_graphicsScene->addRect(x, y, // Start Position
511  elementSize, elementSize, // Rectangle Size
512  outlinePen, fillBrush); // outline/fill options
513  QString img1 = "Image 1 : " + colIterator.key() + "\n";
514  QString param1 = "Parameter 1: " + colIterator.value().at(column) + "\n";
515  QString img2 = "Image 2 : " + rowIterator.key() + "\n";
516  QString param2 = "Parameter 2: " + rowIterator.value().at(row);
517  QString toolTip = "Correlation : "
518  + QString::number( ( *block.value() )(row, column) )
519  + "\n" + img1 + param1 + img2 + param2;
520  rectangle->setToolTip(toolTip);
521  }
522  x += elementSize;
523  }
524  x = startX;
525  y += elementSize;
526  }
527  x = startX;
528  // jump up by the number of rows in the previous block
529  if ( block.hasPrevious() ) {
530  yOffset += block.peekPrevious().value()->size1() * elementSize;
531  }
532  y = startY - yOffset;
533  lastBlock = false;
534  } while ( block.hasPrevious() );
535 
536  startX += block.value()->size2() * elementSize;
537  startY += block.value()->size1() * elementSize;
538  x = startX;
539  y = startY;
540  yOffset = 0;
541  }
542  }
543 
544 
551  int startVX = 20;
552  int startVY = 20;
553  int startHX = 20;
554  int startHY = 20;
555 
556  int elementSize = 10;
557 
558  QList<int> segments;
559  int segmentLength = 0;
560 
561  QMapIterator<QString, QStringList> it( *corrMatrix.imagesAndParameters() );
562  // get list of segment lengths1
563  while ( it.hasNext() ) {
564  it.next();
565  int numOfParams = it.value().count();
566  segmentLength += numOfParams * elementSize;
567  segments.append(segmentLength);
568  }
569 
570  segments.removeLast();
571 
573 
574  QPen pen;
575  pen.setColor(Qt::black);
576  pen.setWidth(1);
577 
578  // Top of matrix, at this point segmentLength is the length of the longest side
579  QGraphicsLineItem *hLine;
580  hLine = new QGraphicsLineItem(startHX, startHY,
581  startHX + segmentLength, startHY);
582  hLine->setPen(pen);
583  m_graphicsScene->addItem(hLine);
584 
585  // Right most side of matrix (edge)
586  QGraphicsLineItem *vLine;
587  vLine = new QGraphicsLineItem(startVX + segmentLength, startVY,
588  startVX + segmentLength, startVY + segmentLength);
589  vLine->setPen(pen);
590  m_graphicsScene->addItem(vLine);
591 
592  int edge = startVX + segmentLength;
593  int currentLength = segmentLength;
594  int currentVX = startVX;
595 
596  //draw the rest of the grid
597  foreach (int segment, segments) {
598  currentVX = startVX + segment;
599  currentLength = segmentLength - segment;
600 
601  vLine = new QGraphicsLineItem(currentVX, startVY,
602  currentVX, startVY + segment);
603 
604  hLine = new QGraphicsLineItem(edge - currentLength, startHY + segment,
605  edge, startHY + segment);
606 
607  vLine->setPen(pen);
608  hLine->setPen(pen);
609  m_graphicsScene->addItem(vLine);
610  m_graphicsScene->addItem(hLine);
611  }
612  }
613 
614 
619  drawElements( *m_matrixOptions->parentMatrix() );
620  }
621 
622 
628 // void MatrixSceneWidget::repaintItems(bool colorScheme) {
629 // if (colorScheme) {
630 // // dont actually use this. just redo the colors?
631 // drawElements( m_directory->project()->correlationMatrix() );
632 // }
633 // else {
634 // foreach ( MatrixElement element, m_graphicsScene->items() ) {
635 // if ( element.correlation() >= m_options->tolerance() ) {
636 // element.setColor( m_options->badCorrelationColor() );
637 // }
638 // else {
639 // element.setColor( m_options->goodCorrelationColor() );
640 // }
641 // }
642 // }
643 // }
644 
645 
652  m_matrixOptions = new MatrixOptions(corrMat, this);
653  connect(m_matrixOptions, SIGNAL( optionsUpdated() ),
654  this, SLOT( redrawElements() ) );
655  }
656 }
void redrawItems()
Redraws all the items in the view.
A graphics scene with improved user-interaction for use with the MatrixSceneWidget.
MatrixGraphicsView * m_graphicsView
The graphics view that displays the scene.
void drawElements(CorrelationMatrix corrMatrix)
Refit scene and items when the widget size changes.
QRectF elementsBoundingRect() const
Returns the bounding rectangle for the images.
This is a container for the correlation matrix that comes from a bundle adjust.
SparseBlockColumnMatrix.
QGraphicsRectItem * m_outlineRect
Rectangle outlining the area where the images go.
This class holds the matrix color and focus information.
Definition: MatrixOptions.h:28
double colorTolerance()
Threshold for what is considered a bad correlation.
ProgressBar * m_progress
Progress bar.
virtual ~MatrixSceneWidget()
Default Destructor.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
virtual bool eventFilter(QObject *obj, QEvent *ev)
Pick the relevant actions given the type of event that occured in the scene.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void visibleRectChanged(QRectF)
Emitted when the visible rectangle is changed.
void drawGrid(CorrelationMatrix corrMatrix)
Draw the lines that will show the columns and blocks for each image.
QList< QAction * > getViewActions()
Accessor for the view actions.
void redrawElements()
Redraw matrix when the focus is changed.
bool contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
This is called by MatrixGraphicsScene::contextMenuEvent.
QColor badCorrelationColor()
The color selected for the correlation values that are above the given threshold. ...
A graphics view that resizes in a more friendly way.
MatrixGraphicsView * getView() const
Accessor for the QGraphicsView.
void elementClicked(QString)
Emitted when an element of the widget is clicked.
QAction * m_quickMapAction
??? (always NULL)
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
MatrixOptions * m_matrixOptions
Options for the correlation matrix.
void setUpOptions(CorrelationMatrix corrMat)
Change item colors when options are changed.
void sendVisibleRectChanged()
This method refits the items in the graphics view.
QGraphicsScene * m_graphicsScene
The graphics scene holds the scene items.
Directory * directory() const
Accessor for the directory.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Directory * m_directory
The directory of the project.
void mouseDoubleClick(QPointF)
Emitted when handling a mouse double-click.
QList< SparseBlockColumnMatrix > * visibleBlocks()
Get the visible part of the matrix.
bool colorScheme()
Use the green-red gradient if false.
QGraphicsScene * getScene() const
Accessor for the QGraphicsScene.
QList< QAction * > supportedActions(CorrelationMatrix *matrix)
Get a list of applicable actions for the elements in this scene.
QProgressBar * getProgress()
Accessor for the widget&#39;s progress bar.
QColor goodCorrelationColor()
The color selected for the correlation values that are below the given threshold. ...
QMap< QString, QStringList > * imagesAndParameters()
Public access for the qmap of images and parameters.