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 }
Isis::MatrixSceneWidget::drawElements
void drawElements(CorrelationMatrix corrMatrix)
Draw elements.
Definition: MatrixSceneWidget.cpp:415
QWidget
QProgressBar
Isis::MatrixSceneWidget::getProgress
QProgressBar * getProgress()
Accessor for the widget's progress bar.
Definition: MatrixSceneWidget.cpp:246
Isis::Directory
Definition: Directory.h:271
Isis::SparseBlockColumnMatrix
SparseBlockColumnMatrix.
Definition: SparseBlockMatrix.h:58
Isis::MatrixOptions::colorScheme
bool colorScheme()
Use the green-red gradient if false.
Definition: MatrixOptions.cpp:116
QList
This is free and unencumbered software released into the public domain.
Definition: BoxcarCachingAlgorithm.h:13
Isis::MatrixSceneWidget::~MatrixSceneWidget
virtual ~MatrixSceneWidget()
Default Destructor.
Definition: MatrixSceneWidget.cpp:154
Isis::ProgressBar
Definition: ProgressBar.h:15
Project.h
Isis::MatrixSceneWidget::m_outlineRect
QGraphicsRectItem * m_outlineRect
Rectangle outlining the area where the images go.
Definition: MatrixSceneWidget.h:137
Isis::MatrixOptions::goodCorrelationColor
QColor goodCorrelationColor()
The color selected for the correlation values that are below the given threshold.
Definition: MatrixOptions.cpp:82
Isis::MatrixOptions::colorTolerance
double colorTolerance()
Threshold for what is considered a bad correlation.
Definition: MatrixOptions.cpp:104
Isis::MatrixSceneWidget::elementsBoundingRect
QRectF elementsBoundingRect() const
Returns the bounding rectangle for the images.
Definition: MatrixSceneWidget.cpp:262
Isis::MatrixSceneWidget::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *ev)
Pick the relevant actions given the type of event that occured in the scene.
Definition: MatrixSceneWidget.cpp:360
Isis::MatrixSceneWidget::m_progress
ProgressBar * m_progress
Progress bar.
Definition: MatrixSceneWidget.h:141
Isis::MatrixOptions
This class holds the matrix color and focus information.
Definition: MatrixOptions.h:28
Isis::CorrelationMatrix
This is a container for the correlation matrix that comes from a bundle adjust.
Definition: CorrelationMatrix.h:61
Isis::MatrixSceneWidget::contextMenuEvent
bool contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
This is called by MatrixGraphicsScene::contextMenuEvent.
Definition: MatrixSceneWidget.cpp:186
Isis::MatrixSceneWidget::getViewActions
QList< QAction * > getViewActions()
Accessor for the view actions.
Definition: MatrixSceneWidget.cpp:287
Isis::MatrixSceneWidget::visibleRectChanged
void visibleRectChanged(QRectF)
Emitted when the visible rectangle is changed.
Isis::MatrixSceneWidget::drawGrid
void drawGrid(CorrelationMatrix corrMatrix)
Draw the lines that will show the columns and blocks for each image.
Definition: MatrixSceneWidget.cpp:550
Isis::MatrixSceneWidget::setUpOptions
void setUpOptions(CorrelationMatrix corrMat)
Change item colors when options are changed.
Definition: MatrixSceneWidget.cpp:651
QGraphicsScene
Isis::MatrixSceneWidget::elementClicked
void elementClicked(QString)
Emitted when an element of the widget is clicked.
Isis::MatrixGraphicsView
A graphics view that resizes in a more friendly way.
Definition: MatrixGraphicsView.h:15
Isis::MatrixSceneWidget::m_graphicsScene
QGraphicsScene * m_graphicsScene
The graphics scene holds the scene items.
Definition: MatrixSceneWidget.h:134
Isis::MatrixSceneWidget::redrawElements
void redrawElements()
Redraw matrix when the focus is changed.
Definition: MatrixSceneWidget.cpp:618
Isis::MatrixSceneWidget::m_quickMapAction
QAction * m_quickMapAction
??? (always NULL)
Definition: MatrixSceneWidget.h:139
Isis::MatrixSceneWidget::sendVisibleRectChanged
void sendVisibleRectChanged()
This method refits the items in the graphics view.
Definition: MatrixSceneWidget.cpp:333
Isis::MatrixSceneWidget::m_directory
Directory * m_directory
The directory of the project.
Definition: MatrixSceneWidget.h:132
Isis::MatrixSceneWidget::getView
MatrixGraphicsView * getView() const
Accessor for the QGraphicsView.
Definition: MatrixSceneWidget.cpp:164
Isis::MatrixOptions::badCorrelationColor
QColor badCorrelationColor()
The color selected for the correlation values that are above the given threshold.
Definition: MatrixOptions.cpp:93
Isis::MatrixSceneWidget::supportedActions
QList< QAction * > supportedActions(CorrelationMatrix *matrix)
Get a list of applicable actions for the elements in this scene.
Definition: MatrixSceneWidget.cpp:305
Isis::CorrelationMatrix::visibleBlocks
QList< SparseBlockColumnMatrix > * visibleBlocks()
Get the visible part of the matrix.
Definition: CorrelationMatrix.cpp:454
Isis::MatrixSceneWidget::m_matrixOptions
MatrixOptions * m_matrixOptions
Options for the correlation matrix.
Definition: MatrixSceneWidget.h:143
QObject
Isis::MatrixSceneWidget::redrawItems
void redrawItems()
Redraws all the items in the view.
Definition: MatrixSceneWidget.cpp:395
Isis::MatrixSceneWidget::m_graphicsView
MatrixGraphicsView * m_graphicsView
The graphics view that displays the scene.
Definition: MatrixSceneWidget.h:135
Isis::MatrixGraphicsScene
A graphics scene with improved user-interaction for use with the MatrixSceneWidget.
Definition: MatrixGraphicsScene.h:21
Isis::MatrixSceneWidget::getScene
QGraphicsScene * getScene() const
Accessor for the QGraphicsScene.
Definition: MatrixSceneWidget.cpp:174
Isis::CorrelationMatrix::imagesAndParameters
QMap< QString, QStringList > * imagesAndParameters()
Public access for the qmap of images and parameters.
Definition: CorrelationMatrix.cpp:417
QGraphicsRectItem
Isis::MatrixSceneWidget::directory
Directory * directory() const
Accessor for the directory.
Definition: MatrixSceneWidget.cpp:277
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::MatrixSceneWidget::mouseDoubleClick
void mouseDoubleClick(QPointF)
Emitted when handling a mouse double-click.