Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "QmitkTransferFunctionCanvas.h"
00019
00020 #include <itkObject.h>
00021
00022 #include <QColorDialog>
00023 #include <QPainter>
00024 #include <QMouseEvent>
00025
00026 void mitk::SimpleHistogram::ComputeFromImage( Image::Pointer source )
00027 {
00028 valid = false;
00029
00030
00031 {
00032 min=0;
00033 max=1;
00034 first=0;
00035 last=1;
00036 }
00037
00038 {
00039 int typInt=0;
00040 {
00041 const std::type_info* typ=source->GetPixelType().GetTypeId();
00042 if (*typ == typeid(unsigned char )) typInt=0;
00043 else if(*typ == typeid(signed char )) typInt=1;
00044 else if(*typ == typeid(unsigned short)) typInt=2;
00045 else if(*typ == typeid(signed short )) typInt=3;
00046 else
00047 {
00048 MITK_WARN << "SimpleHistogram currently only supports un/signed char/short";
00049 return;
00050 }
00051 }
00052
00053
00054 first=-32768; last=65535;
00055
00056 if(histogram)
00057 delete histogram;
00058
00059 histogram = new CountType[last-first+1];
00060 memset(histogram,0,sizeof(CountType)*(last-first+1));
00061 highest = 0;
00062 max = first - 1;
00063 min = last + 1;
00064
00065 unsigned int num=1;
00066 for(unsigned int r=0;r<source->GetDimension();r++)
00067 num*=source->GetDimension(r);
00068
00069
00070
00071 void *src=source->GetData();
00072
00073 do
00074 {
00075 int value;
00076
00077 switch(typInt)
00078 {
00079 case 0: { unsigned char *t=(unsigned char *)src; value=*t++; src=(void*)t; } break;
00080 case 1: { signed char *t=( signed char *)src; value=*t++; src=(void*)t; } break;
00081 case 2: { unsigned short *t=(unsigned short*)src; value=*t++; src=(void*)t; } break;
00082 case 3: { signed short *t=( signed short*)src; value=*t++; src=(void*)t; } break;
00083 }
00084
00085 if(value >= first && value <= last)
00086 {
00087 if(value < min) min = value;
00088 if(value > max) max = value;
00089 CountType tmp = ++histogram[value-first];
00090 if(tmp > highest) highest = tmp;
00091 }
00092 }
00093 while(--num);
00094
00095
00096 }
00097
00098 invLogHighest = 1.0/log(double(highest));
00099 valid = true;
00100 }
00101
00102
00103 float mitk::SimpleHistogram::GetRelativeBin( float left, float right )
00104 {
00105 if( !valid )
00106 return 0.0f;
00107
00108 int iLeft = floorf(left);
00109 int iRight = ceilf(right);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 CountType maximum = 0;
00126
00127 for( int i = iLeft; i <= iRight ; i++)
00128 {
00129 int posInArray = i - first;
00130 if( histogram[posInArray] > maximum ) maximum = histogram[posInArray];
00131 }
00132
00133 return float(log(double(maximum))*invLogHighest);
00134
00135
00136
00137
00138 }
00139
00140
00141 QmitkTransferFunctionCanvas::QmitkTransferFunctionCanvas(QWidget * parent,
00142 Qt::WindowFlags f) :
00143 QWidget(parent, f), m_GrabbedHandle(-1), m_Lower(0.0f), m_Upper(1.0f), m_Min(
00144 0.0f), m_Max(1.0f)
00145 {
00146 setEnabled(false);
00147 setFocusPolicy(Qt::ClickFocus);
00148 m_LineEditAvailable = false;
00149 }
00150
00151 void QmitkTransferFunctionCanvas::paintEvent(QPaintEvent* ev)
00152 {
00153 QWidget::paintEvent(ev);
00154 }
00155
00156 std::pair<int,int> QmitkTransferFunctionCanvas::FunctionToCanvas(
00157 std::pair<vtkFloatingPointType,vtkFloatingPointType> functionPoint)
00158 {
00159
00160 return std::make_pair((int) ((functionPoint.first - m_Lower) / (m_Upper
00161 - m_Lower) * contentsRect().width()) + contentsRect().x(), (int) (contentsRect().height() * (1 - functionPoint.second)) + contentsRect().y());
00162 }
00163
00164 std::pair<vtkFloatingPointType,vtkFloatingPointType> QmitkTransferFunctionCanvas::CanvasToFunction(
00165 std::pair<int,int> canvasPoint)
00166 {
00167
00168 return std::make_pair((canvasPoint.first - contentsRect().x()) * (m_Upper - m_Lower) / contentsRect().width()
00169 + m_Lower, 1.0 - (vtkFloatingPointType) (canvasPoint.second - contentsRect().y()) / contentsRect().height());
00170 }
00171
00172 void QmitkTransferFunctionCanvas::mouseDoubleClickEvent(QMouseEvent* mouseEvent)
00173 {
00174 int nearHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
00175 if (nearHandle != -1)
00176 {
00177 this->DoubleClickOnHandle(nearHandle);
00178 }
00179 }
00180
00183 int QmitkTransferFunctionCanvas::GetNearHandle(int , int ,
00184 unsigned int )
00185 {
00186 return -1;
00187 }
00188
00189
00190 void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent* mouseEvent)
00191 {
00192
00193 if (m_LineEditAvailable)
00194 {
00195 m_XEdit->clear();
00196 if(m_YEdit)
00197 m_YEdit->clear();
00198 }
00199
00200 m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
00201
00202 if ( (mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1)
00203 {
00204 this->AddFunctionPoint(
00205 this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(),
00206 mouseEvent->pos().y())).first,
00207 this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second);
00208 m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(),
00209 mouseEvent->pos().y());
00210 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00211 }
00212 else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1)
00213 {
00214 this->RemoveFunctionPoint(this->GetFunctionX(m_GrabbedHandle));
00215 m_GrabbedHandle = -1;
00216 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00217 }
00218 update();
00219
00220
00221 }
00222
00223 void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent* mouseEvent)
00224 {
00225 if (m_GrabbedHandle != -1)
00226 {
00227 std::pair<vtkFloatingPointType,vtkFloatingPointType>
00228 newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(),
00229 mouseEvent->y()));
00230
00231
00232 {
00233
00234 if( m_GrabbedHandle > 0 )
00235 if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1))
00236 newPos.first = this->GetFunctionX(m_GrabbedHandle);
00237
00238
00239 if( m_GrabbedHandle < this->GetFunctionSize()-1 )
00240 if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1))
00241 newPos.first = this->GetFunctionX(m_GrabbedHandle);
00242
00243
00244 if (newPos.first < m_Min) newPos.first = m_Min;
00245 else if (newPos.first > m_Max) newPos.first = m_Max;
00246 }
00247
00248
00249 {
00250 if (newPos.second < 0.0) newPos.second = 0.0;
00251 else if (newPos.second > 1.0) newPos.second = 1.0;
00252 }
00253
00254
00255 this->MoveFunctionPoint(m_GrabbedHandle, newPos);
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 update();
00272
00273
00274 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00275
00276 }
00277 }
00278
00279 void QmitkTransferFunctionCanvas::mouseReleaseEvent(QMouseEvent*)
00280 {
00281
00282 update();
00283 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00284 }
00285
00286 void QmitkTransferFunctionCanvas::PaintHistogram(QPainter &p)
00287 {
00288 if(m_Histogram)
00289 {
00290 p.save();
00291
00292 p.setPen(Qt::gray);
00293
00294 int displayWidth = contentsRect().width();
00295 int displayHeight = contentsRect().height();
00296
00297 int windowLeft = m_Lower;
00298 int windowRight = m_Upper;
00299
00300 double step = (windowRight-windowLeft)/double(displayWidth);
00301
00302 double pos = windowLeft;
00303
00304 for (int x = 0; x < displayWidth; x++)
00305 {
00306 float left = pos;
00307 float right = pos + step;
00308
00309 float height = m_Histogram->GetRelativeBin( left , right );
00310
00311 if (height >= 0)
00312 p.drawLine(x, displayHeight*(1-height), x, displayHeight);
00313
00314 pos += step;
00315 }
00316
00317 p.restore();
00318 }
00319 }
00320
00321
00322
00323
00324 void QmitkTransferFunctionCanvas::keyPressEvent(QKeyEvent * e)
00325 {
00326 if( m_GrabbedHandle == -1)
00327 return;
00328
00329 switch(e->key())
00330 {
00331 case Qt::Key_Delete:
00332 if(this->GetFunctionSize() > 1)
00333 {
00334 this->RemoveFunctionPoint(GetFunctionX(m_GrabbedHandle));
00335 m_GrabbedHandle = -1;
00336 }
00337 break;
00338
00339 case Qt::Key_Left:
00340 this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)-1 , GetFunctionY(m_GrabbedHandle))));
00341 break;
00342
00343 case Qt::Key_Right:
00344 this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)+1 , GetFunctionY(m_GrabbedHandle))));
00345 break;
00346
00347 case Qt::Key_Up:
00348 this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)+0.001)));
00349 break;
00350
00351 case Qt::Key_Down:
00352 this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)-0.001)));
00353 break;
00354 }
00355
00356 update();
00357 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00358 }
00359
00360
00361 void QmitkTransferFunctionCanvas::SetImmediateUpdate(bool state)
00362 {
00363 m_ImmediateUpdate = state;
00364 }