Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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)