Medical Imaging Interaction Toolkit  2018.4.99-389bf124
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include <itkObject.h>
16 
17 #include <QColorDialog>
18 #include <QMouseEvent>
19 #include <QPainter>
20 
22  : QWidget(parent, f),
23  m_GrabbedHandle(-1),
24  m_Lower(0.0),
25  m_Upper(1.0),
26  m_Min(0.0),
27  m_Max(1.0),
28  m_Histogram(nullptr),
29  m_ImmediateUpdate(false),
30  m_Range(0.0f),
31  m_LineEditAvailable(false),
32  m_XEdit(nullptr),
33  m_YEdit(nullptr)
34 {
35  setEnabled(false);
36  setFocusPolicy(Qt::ClickFocus);
37 }
38 
40 {
41  QWidget::paintEvent(ev);
42 }
43 
44 std::pair<int, int> QmitkTransferFunctionCanvas::FunctionToCanvas(std::pair<double, double> functionPoint)
45 {
46  return std::make_pair(
47  (int)((functionPoint.first - m_Lower) / (m_Upper - m_Lower) * contentsRect().width()) + contentsRect().x(),
48  (int)(contentsRect().height() * (1 - functionPoint.second)) + contentsRect().y());
49 }
50 
51 std::pair<double, double> QmitkTransferFunctionCanvas::CanvasToFunction(std::pair<int, int> canvasPoint)
52 {
53  return std::make_pair(
54  (canvasPoint.first - contentsRect().x()) * (m_Upper - m_Lower) / contentsRect().width() + m_Lower,
55  1.0 - (double)(canvasPoint.second - contentsRect().y()) / contentsRect().height());
56 }
57 
59 {
60  int nearHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
61  if (nearHandle != -1)
62  {
63  this->DoubleClickOnHandle(nearHandle);
64  }
65 }
66 
69 int QmitkTransferFunctionCanvas::GetNearHandle(int, int, unsigned int)
70 {
71  return -1;
72 }
73 
74 void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent *mouseEvent)
75 {
77  {
78  m_XEdit->clear();
79  if (m_YEdit)
80  m_YEdit->clear();
81  }
82 
83  m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
84 
85  if ((mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1)
86  {
87  this->AddFunctionPoint(this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(), mouseEvent->pos().y())).first,
88  this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second);
89  m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
91  }
92  else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1)
93  {
95  m_GrabbedHandle = -1;
97  }
98  update();
99 }
100 
101 void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent *mouseEvent)
102 {
103  if (m_GrabbedHandle != -1)
104  {
105  std::pair<double, double> newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y()));
106 
107  // X Clamping
108  {
109  // Check with predecessor
110  if (m_GrabbedHandle > 0)
111  if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1))
112  newPos.first = this->GetFunctionX(m_GrabbedHandle);
113 
114  // Check with sucessor
115  if (m_GrabbedHandle < this->GetFunctionSize() - 1)
116  if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1))
117  newPos.first = this->GetFunctionX(m_GrabbedHandle);
118 
119  // Clamping to histogramm
120  if (newPos.first < m_Min)
121  newPos.first = m_Min;
122  else if (newPos.first > m_Max)
123  newPos.first = m_Max;
124  }
125 
126  // Y Clamping
127  {
128  if (newPos.second < 0.0)
129  newPos.second = 0.0;
130  else if (newPos.second > 1.0)
131  newPos.second = 1.0;
132  }
133 
134  // Move selected point
135  this->MoveFunctionPoint(m_GrabbedHandle, newPos);
136 
137  update();
138 
140  }
141 }
142 
144 {
145  update();
147 }
148 
150 {
151  if (m_Histogram)
152  {
153  p.save();
154 
155  p.setPen(Qt::gray);
156 
157  int displayWidth = contentsRect().width();
158  int displayHeight = contentsRect().height();
159 
160  double windowLeft = m_Lower;
161  double windowRight = m_Upper;
162 
163  double step = (windowRight - windowLeft) / double(displayWidth);
164 
165  double pos = windowLeft;
166 
167  for (int x = 0; x < displayWidth; x++)
168  {
169  double left = pos;
170  double right = pos + step;
171 
172  float height = m_Histogram->GetRelativeBin(left, right);
173 
174  if (height >= 0)
175  p.drawLine(x, displayHeight * (1 - height), x, displayHeight);
176 
177  pos += step;
178  }
179 
180  p.restore();
181  }
182 }
183 
185 {
186  if (m_GrabbedHandle == -1)
187  return;
188 
189  switch (e->key())
190  {
191  case Qt::Key_Delete:
192  if (this->GetFunctionSize() > 1)
193  {
195  m_GrabbedHandle = -1;
196  }
197  break;
198 
199  case Qt::Key_Left:
200  this->MoveFunctionPoint(
203  break;
204 
205  case Qt::Key_Right:
206  this->MoveFunctionPoint(
209  break;
210 
211  case Qt::Key_Up:
212  this->MoveFunctionPoint(
215  break;
216 
217  case Qt::Key_Down:
218  this->MoveFunctionPoint(
221  break;
222  }
223 
224  update();
226 }
227 
228 // Update immediatly while changing the transfer function
230 {
231  m_ImmediateUpdate = state;
232 }
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)