Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkTransferFunctionCanvas.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 
19 #include <itkObject.h>
20 
21 #include <QColorDialog>
22 #include <QMouseEvent>
23 #include <QPainter>
24 
26  : QWidget(parent, f),
27  m_GrabbedHandle(-1),
28  m_Lower(0.0),
29  m_Upper(1.0),
30  m_Min(0.0),
31  m_Max(1.0),
32  m_Histogram(nullptr),
33  m_ImmediateUpdate(false),
34  m_Range(0.0f),
35  m_LineEditAvailable(false),
36  m_XEdit(nullptr),
37  m_YEdit(nullptr)
38 {
39  setEnabled(false);
40  setFocusPolicy(Qt::ClickFocus);
41 }
42 
44 {
45  QWidget::paintEvent(ev);
46 }
47 
48 std::pair<int, int> QmitkTransferFunctionCanvas::FunctionToCanvas(std::pair<double, double> functionPoint)
49 {
50  return std::make_pair(
51  (int)((functionPoint.first - m_Lower) / (m_Upper - m_Lower) * contentsRect().width()) + contentsRect().x(),
52  (int)(contentsRect().height() * (1 - functionPoint.second)) + contentsRect().y());
53 }
54 
55 std::pair<double, double> QmitkTransferFunctionCanvas::CanvasToFunction(std::pair<int, int> canvasPoint)
56 {
57  return std::make_pair(
58  (canvasPoint.first - contentsRect().x()) * (m_Upper - m_Lower) / contentsRect().width() + m_Lower,
59  1.0 - (double)(canvasPoint.second - contentsRect().y()) / contentsRect().height());
60 }
61 
63 {
64  int nearHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
65  if (nearHandle != -1)
66  {
67  this->DoubleClickOnHandle(nearHandle);
68  }
69 }
70 
73 int QmitkTransferFunctionCanvas::GetNearHandle(int, int, unsigned int)
74 {
75  return -1;
76 }
77 
78 void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent *mouseEvent)
79 {
81  {
82  m_XEdit->clear();
83  if (m_YEdit)
84  m_YEdit->clear();
85  }
86 
87  m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
88 
89  if ((mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1)
90  {
91  this->AddFunctionPoint(this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(), mouseEvent->pos().y())).first,
92  this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second);
93  m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
95  }
96  else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1)
97  {
99  m_GrabbedHandle = -1;
101  }
102  update();
103 }
104 
105 void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent *mouseEvent)
106 {
107  if (m_GrabbedHandle != -1)
108  {
109  std::pair<double, double> newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y()));
110 
111  // X Clamping
112  {
113  // Check with predecessor
114  if (m_GrabbedHandle > 0)
115  if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1))
116  newPos.first = this->GetFunctionX(m_GrabbedHandle);
117 
118  // Check with sucessor
119  if (m_GrabbedHandle < this->GetFunctionSize() - 1)
120  if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1))
121  newPos.first = this->GetFunctionX(m_GrabbedHandle);
122 
123  // Clamping to histogramm
124  if (newPos.first < m_Min)
125  newPos.first = m_Min;
126  else if (newPos.first > m_Max)
127  newPos.first = m_Max;
128  }
129 
130  // Y Clamping
131  {
132  if (newPos.second < 0.0)
133  newPos.second = 0.0;
134  else if (newPos.second > 1.0)
135  newPos.second = 1.0;
136  }
137 
138  // Move selected point
139  this->MoveFunctionPoint(m_GrabbedHandle, newPos);
140 
141  update();
142 
144  }
145 }
146 
148 {
149  update();
151 }
152 
154 {
155  if (m_Histogram)
156  {
157  p.save();
158 
159  p.setPen(Qt::gray);
160 
161  int displayWidth = contentsRect().width();
162  int displayHeight = contentsRect().height();
163 
164  double windowLeft = m_Lower;
165  double windowRight = m_Upper;
166 
167  double step = (windowRight - windowLeft) / double(displayWidth);
168 
169  double pos = windowLeft;
170 
171  for (int x = 0; x < displayWidth; x++)
172  {
173  double left = pos;
174  double right = pos + step;
175 
176  float height = m_Histogram->GetRelativeBin(left, right);
177 
178  if (height >= 0)
179  p.drawLine(x, displayHeight * (1 - height), x, displayHeight);
180 
181  pos += step;
182  }
183 
184  p.restore();
185  }
186 }
187 
189 {
190  if (m_GrabbedHandle == -1)
191  return;
192 
193  switch (e->key())
194  {
195  case Qt::Key_Delete:
196  if (this->GetFunctionSize() > 1)
197  {
199  m_GrabbedHandle = -1;
200  }
201  break;
202 
203  case Qt::Key_Left:
204  this->MoveFunctionPoint(
207  break;
208 
209  case Qt::Key_Right:
210  this->MoveFunctionPoint(
213  break;
214 
215  case Qt::Key_Up:
216  this->MoveFunctionPoint(
219  break;
220 
221  case Qt::Key_Down:
222  this->MoveFunctionPoint(
225  break;
226  }
227 
228  update();
230 }
231 
232 // Update immediatly while changing the transfer function
234 {
235  m_ImmediateUpdate = state;
236 }
virtual void paintEvent(QPaintEvent *e) override
virtual float GetRelativeBin(double start, double end) const =0
TODO: (What should this method do?)
virtual double GetFunctionX(int index)=0
virtual int AddFunctionPoint(double x, double val)=0
void mousePressEvent(QMouseEvent *mouseEvent) override
virtual void MoveFunctionPoint(int index, std::pair< double, double > pos)=0
virtual int GetNearHandle(int x, int y, unsigned int maxSquaredDistance=32)=0
void mouseDoubleClickEvent(QMouseEvent *mouseEvent) override
QmitkTransferFunctionCanvas(QWidget *parent=nullptr, Qt::WindowFlags f=nullptr)
virtual void DoubleClickOnHandle(int handle)=0
virtual void RemoveFunctionPoint(double x)=0
static RenderingManager * GetInstance()
std::pair< double, double > ValidateCoord(std::pair< double, double > x)
virtual double GetFunctionY(int index)=0
virtual int GetFunctionSize()=0
void mouseReleaseEvent(QMouseEvent *mouseEvent) override
std::pair< int, int > FunctionToCanvas(std::pair< double, double >)
void keyPressEvent(QKeyEvent *e) override
std::pair< double, double > CanvasToFunction(std::pair< int, int >)
void mouseMoveEvent(QMouseEvent *mouseEvent) override
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)