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