00001 #include <math.h>
00002 #include <QPainter>
00003 #include <QPainterPath>
00004 #include <QtDebug>
00005 #include <QFileDialog>
00006 #include <QMessageBox>
00007 #include <QMouseEvent>
00008 #include "TransferFunction.h"
00009 #include "ColorPicker.h"
00010
00011 TransferFunction::TransferFunction(QWidget *parent) : QWidget(parent)
00012 {
00013 this->parent = parent;
00014 volume = 0;
00015 height = -1;
00016 widthMax = -1;
00017 normHistoVals = 0;
00018 normHistoVals = 0;
00019 normScaledHistoVals = 0;
00020 zoomFactor = 0;
00021 scaleFactor = 1.0;
00022 marginBottom = marginRight = 0;
00023 transferFunction = 0;
00024
00025 updateAsked = false;
00026 timerIdentifier = startTimer(50);
00027 }
00028
00029 TransferFunction::~TransferFunction()
00030 {
00031 killTimer(timerIdentifier);
00032 if(normHistoVals)
00033 {
00034 delete [] normHistoVals;
00035 }
00036 if(normScaledHistoVals)
00037 {
00038 delete [] normScaledHistoVals;
00039 }
00040 if(transferFunction)
00041 {
00042 delete [] transferFunction;
00043 }
00044 removeAllVertices();
00045 }
00046
00047 void TransferFunction::update()
00048 {
00049 updateAsked = true;
00050 }
00051
00052 void TransferFunction::timerEvent(QTimerEvent *event)
00053 {
00054 if(updateAsked)
00055 {
00056 updateAsked = false;
00057 QWidget::update();
00058 }
00059 }
00060
00061 QSize TransferFunction::sizeHint() const
00062 {
00063 return QSize(scaledWidth, height);
00064 }
00065
00066
00067 void TransferFunction::loadTfFile()
00068 {
00069 QString fileName = QFileDialog::getOpenFileName(0,
00070 "Load Transfer Function", curDir,
00071 "Transfer Function (*.tf);;All Files (*)");
00072 if(fileName!=0) {
00073 curDir = fileName;
00074 qDebug() << "Pfad vom File: " << fileName;
00075
00076 QFile *file = new QFile(fileName);
00077
00078 if(!file->open(QIODevice::ReadOnly | QIODevice::Unbuffered))
00079 {
00080 qDebug() << "could not open";
00081 return;
00082 }
00083
00084 int count, tmpInt;
00085 Vertex *v;
00086 QColor color;
00087
00088 file->read((char*)&count, 4);
00089
00090 removeAllVertices();
00091 for(int i = 0;i < count;++i)
00092 {
00093 v = new Vertex();
00094 file->read((char*)&tmpInt, 4);
00095 v->x = tmpInt;
00096 v->xScaled = (int)floor(tmpInt / scaleFactor + 0.5);
00097
00098 file->read((char*)&tmpInt, 4);
00099 v->color.setRed(tmpInt);
00100 file->read((char*)&tmpInt, 4);
00101 v->color.setGreen(tmpInt);
00102 file->read((char*)&tmpInt, 4);
00103 v->color.setBlue(tmpInt);
00104 file->read((char*)&tmpInt, 4);
00105 v->color.setAlpha(tmpInt);
00106
00107 vertices.insert(v);
00108 }
00109 file->close();
00110 delete file;
00111
00112 updateTransferfunction();
00113 update();
00114 qDebug() << "loaded";
00115 }
00116 }
00117
00118 void TransferFunction::saveTfFile()
00119 {
00120 QString fileName = QFileDialog::getSaveFileName(0,
00121 "Save Transfer Function", curDir,
00122 "Transfer Function (*.tf);;All Files (*)");
00123 if(fileName!=0) {
00124 curDir = fileName;
00125 qDebug() << "Pfad vom File: " << fileName;
00126
00127 QFile *file = new QFile(fileName);
00128
00129 if(!file->open(QIODevice::WriteOnly | QIODevice::Unbuffered))
00130 {
00131 qDebug() << "could not open";
00132 return;
00133 }
00134
00135 int tmpInt = vertices.size();
00136 file->write((char*)&tmpInt, 4);
00137
00138 IteratorVertices iter;
00139 for(iter = vertices.begin();iter != vertices.end(); ++iter)
00140 {
00141 tmpInt = (*iter)->x;
00142 file->write((char*)&tmpInt, 4);
00143 tmpInt = (*iter)->color.red();
00144 file->write((char*)&tmpInt, 4);
00145 tmpInt = (*iter)->color.green();
00146 file->write((char*)&tmpInt, 4);
00147 tmpInt = (*iter)->color.blue();
00148 file->write((char*)&tmpInt, 4);
00149 tmpInt = (*iter)->color.alpha();
00150 file->write((char*)&tmpInt, 4);
00151 }
00152 file->close();
00153 delete file;
00154
00155 qDebug() << "saved";
00156 }
00157 }
00158
00159 void TransferFunction::mousePressEvent(QMouseEvent *event)
00160 {
00161 unselectAllVertices();
00162 Vertex *tempV = newVertex(event->x(), event->y());
00163 IteratorVertices iterHit = containsNearVertex(tempV);
00164 if(iterHit._Has_container())
00165 {
00166 Vertex *hit = *iterHit;
00167 select(hit);
00168 movingVertex = iterHit;
00169 }
00170 update();
00171 }
00172
00173 void TransferFunction::mouseReleaseEvent(QMouseEvent * event)
00174 {
00175
00176
00177
00178
00179 }
00180
00181 void TransferFunction::mouseMoveEvent(QMouseEvent* event)
00182 {
00183 if(event->buttons() == Qt::LeftButton)
00184 {
00185 if((*movingVertex)->selected) {
00186
00187 int xNew = event->pos().x();
00188 int yNew = event->pos().y();
00189
00190
00191 if(movingVertex==vertices.begin() || movingVertex==(--vertices.end()))
00192 {
00193 xNew = (*movingVertex)->xScaled;
00194 }
00195 else
00196 {
00197 IteratorVertices iterTemp = movingVertex;
00198
00199 iterTemp++;
00200 if((*iterTemp)->xScaled <= xNew)
00201 {
00202 xNew = (*iterTemp)->xScaled - 1;
00203 }
00204 else
00205 {
00206 iterTemp--;
00207 iterTemp--;
00208 if((*iterTemp)->xScaled >= xNew)
00209 {
00210 xNew = (*iterTemp)->xScaled + 1;
00211 }
00212 }
00213 }
00214
00215 if(yNew<0)
00216 {
00217 yNew = 0;
00218 } else if(yNew>255)
00219 {
00220 yNew = 255;
00221 }
00222
00223 (*movingVertex)->setPos(xNew*scaleFactor, xNew, yNew);
00224 updateTransferfunction();
00225 update();
00226 }
00227 }
00228 }
00229
00230
00231 void TransferFunction::mouseDoubleClickEvent(QMouseEvent* event)
00232 {
00233 if(event->button() == Qt::LeftButton)
00234 {
00235 unselectAllVertices();
00236 Vertex *tempV = newVertex(event->x(), event->y());
00237 IteratorVertices iterHit = containsNearVertex(tempV);
00238 if(iterHit._Has_container())
00239 {
00240 Vertex *hit = *iterHit;
00241 select(hit);
00242 delete tempV;
00243 ColorPicker colorPicker(this);
00244 colorPicker.setColor(hit->color);
00245 if(colorPicker.startPicker())
00246 {
00247 QColor newColor = colorPicker.getColor();
00248 newColor.setAlpha(hit->color.alpha());
00249 hit->color = newColor;
00250 updateTransferfunction();
00251 }
00252 }
00253 else
00254 {
00255 addVertex(tempV);
00256 select(tempV);
00257 }
00258
00259 update();
00260 }
00261 else if(event->button() == Qt::RightButton)
00262 {
00263 Vertex *tempV = newVertex(event->x(), event->y());
00264 IteratorVertices iterHit = containsNearVertex(tempV);
00265 if(*iterHit)
00266 {
00267 Vertex *hit = *iterHit;
00268 unselect(hit);
00269 removeVertex(hit);
00270 delete tempV;
00271
00272 update();
00273 }
00274
00275 }
00276 }
00277
00278 int TransferFunction::width() const
00279 {
00280 return ((QScrollArea*)parent)->viewport()->width();
00281 }
00282
00283 void TransferFunction::setVolume(Volume *volume)
00284 {
00285 this->volume = volume;
00286 height = 255;
00287 widthMax = volume->getDataRange();
00288
00289 initHisto();
00290 initTransferfunction();
00291 this->adjustSize();
00292 update();
00293 }
00294
00295 void TransferFunction::setZoomFactor(int value)
00296 {
00297 zoomFactor = value;
00298 updateSize();
00299 }
00300
00301 void TransferFunction::updateSize()
00302 {
00303 updateScale();
00304 this->adjustSize();
00305 }
00306
00307 void TransferFunction::initTransferfunction()
00308 {
00309 if(transferFunction)
00310 {
00311 delete [] transferFunction;
00312 }
00313 transferFunction = new TransferColor[widthMax];
00314
00315 unselectAllVertices();
00316 removeAllVertices();
00317
00318 addVertex(0, QColor(255, 255, 255, 255));
00319 addVertex(scaledWidth, 0);
00320 movingVertex = vertices.begin();
00321 updateTransferfunction();
00322
00323 }
00324
00325 void TransferFunction::initHisto()
00326 {
00327 if(normHistoVals)
00328 {
00329 delete [] normHistoVals;
00330 }
00331 normHistoVals = new unsigned int[widthMax];
00332
00333 normScaledHistoVals = new unsigned int[widthMax];
00334
00335 const std::vector<unsigned int>* histoVals = volume->getHistogramm();
00336
00337 double histoMaxValue = (double)volume->getHistHeight();
00338 double logBasis = log(pow(histoMaxValue + 1, 1.0/(double)height));
00339
00340
00341 for(int x = 0;x<widthMax;x++)
00342 {
00343
00344 double y2_lin = ((double)(*histoVals)[x]/histoMaxValue)*height;
00345
00346 double y2_log = log((double)(*histoVals)[x]+1)/logBasis;
00347
00348
00349
00350
00351 double ratio = y2_log / height;
00352 normHistoVals[x] = height - (ratio*y2_log+(1-ratio)*y2_lin);
00353 }
00354
00355 updateScale();
00356 }
00357
00358 void TransferFunction::updateTransferfunction()
00359 {
00360 IteratorVertices iter = vertices.begin(), iterPrev = iter;
00361 iter++;
00362 for(; iter != vertices.end(); iterPrev = iter, ++iter)
00363 {
00364 int r1 = (*iterPrev)->color.red();
00365 int g1 = (*iterPrev)->color.green();
00366 int b1 = (*iterPrev)->color.blue();
00367 int r2 = (*iter)->color.red();
00368 int g2 = (*iter)->color.green();
00369 int b2 = (*iter)->color.blue();
00370
00371 int x1 = (*iterPrev)->x;
00372 int y1 = 255-(*iterPrev)->color.alpha();
00373 int x2 = (*iter)->x;
00374 int y2 = 255-(*iter)->color.alpha();
00375
00376
00377
00378 double a = y1;
00379 double c = 3.0*(y2-y1);
00380 double d = (-2)*(y2-y1);
00381
00382 transferFunction[x1].r = (unsigned char)r1;
00383 transferFunction[x1].g = (unsigned char)g1;
00384 transferFunction[x1].b = (unsigned char)b1;
00385 transferFunction[x1].a = (unsigned char)y1;
00386 for(int i=x1+1;i<x2;i++)
00387 {
00388 double part = (i-x1)/((double)abs(x2-x1));
00389 double xi = (i-x1)/((double)(x2-x1));
00390 transferFunction[i].r = (unsigned char)floor((1.0-part)*r1 + part*r2 +0.5);
00391 transferFunction[i].g = (unsigned char)floor((1.0-part)*g1 + part*g2 +0.5);
00392 transferFunction[i].b = (unsigned char)floor((1.0-part)*b1 + part*b2 +0.5);
00393 transferFunction[i].a = (unsigned char)floor((a+c*xi*xi+d*xi*xi*xi)+0.5);
00394 }
00395 }
00396 emit getTransferFunction((unsigned int*)transferFunction, widthMax);
00397 }
00398
00399 void TransferFunction::paintEvent(QPaintEvent* event)
00400 {
00401 if(volume!=0) {
00402 QPainter painter(this);
00403
00404
00405 painter.setPen(Qt::blue);
00406
00407
00408
00409
00410 for(int x = 0;x<scaledWidth;x++)
00411 {
00412 if(normScaledHistoVals[x] != height)
00413 {
00414 QColor color(transferFunction[(int)(x*scaleFactor)].r,
00415 transferFunction[(int)(x*scaleFactor)].g,
00416 transferFunction[(int)(x*scaleFactor)].b);
00417 painter.setPen(color);
00418
00419 painter.drawLine(x, height, x, normScaledHistoVals[x]);
00420 }
00421 }
00422
00423
00424
00425 QPainterPath path;
00426 path.moveTo(0, (*vertices.begin())->color.alpha());
00427
00428 IteratorVertices iter = vertices.begin(), iterPrev = iter;
00429 (*iter)->drawVertex(painter);
00430 iter++;
00431 for(; iter != vertices.end(); iterPrev = iter, ++iter)
00432 {
00433 int y = (*iter)->color.alpha();
00434 int x = (*iter)->xScaled;
00435 int prevY = (*iterPrev)->color.alpha();
00436 int prevX = (*iterPrev)->xScaled;
00437
00438 path.cubicTo(prevX+(x-prevX)/2, prevY, x-(x-prevX)/2, y, x, y);
00439
00440 (*iter)->drawVertex(painter);
00441 }
00442
00443 painter.setPen(QPen(QColor(0, 0, 0), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
00444 painter.setBrush(Qt::NoBrush);
00445 painter.setRenderHint(QPainter::Antialiasing);
00446 painter.drawPath(path);
00447 }
00448 }
00449
00450 void TransferFunction::Vertex::drawVertex(QPainter& painter)
00451 {
00452 int alphaFill;
00453 QColor borderColor;
00454
00455 if(selected)
00456 {
00457 alphaFill = 255;
00458 borderColor = QColor(Qt::gray);
00459 } else
00460 {
00461 alphaFill = 100;
00462 borderColor = QColor(Qt::black);
00463 }
00464
00465 QColor curColor = color;
00466 painter.setPen(borderColor);
00467 painter.setBrush(QBrush(QColor(curColor.red(), curColor.green(), curColor.blue(), alphaFill)));
00468 painter.drawRect(xScaled - Vertex::DRAW_SIZE/2,
00469 color.alpha() - Vertex::DRAW_SIZE/2, Vertex::DRAW_SIZE, Vertex::DRAW_SIZE);
00470 }
00471
00472 void TransferFunction::updateScale()
00473 {
00474
00475 scaledWidth = ((double)(widthMax - width())) / 1000.0 * zoomFactor + width();
00476 scaleFactor = ((double)widthMax)/((double)scaledWidth);
00477
00478 for(int i=0;i<widthMax;i++)
00479 {
00480 normScaledHistoVals[i] = 0;
00481 }
00482
00483 for(int x=0;x<widthMax;x++)
00484 {
00485
00486 int targetIndex = (int)(floor((x/scaleFactor)+0.5));
00487
00488
00489 if(normScaledHistoVals[targetIndex] == 0) {
00490 normScaledHistoVals[targetIndex] = normHistoVals[x];
00491 } else {
00492 normScaledHistoVals[targetIndex] = (normScaledHistoVals[targetIndex] + normHistoVals[x])/2;
00493 }
00494 }
00495
00496 for(IteratorVertices iter = vertices.begin(); iter != vertices.end(); ++iter)
00497 {
00498 (*iter)->xScaled = (int)(floor(((*iter)->x/scaleFactor)+0.5));
00499 }
00500 }
00501
00502
00503
00504 TransferFunction::Vertex* TransferFunction::newVertex(int xScaled, int alpha)
00505 {
00506 return new Vertex((int)floor(xScaled*scaleFactor+0.5), xScaled, QColor(255, 255, 255, alpha));
00507 }
00508
00509
00510 TransferFunction::Vertex* TransferFunction::addVertex(int scaledX, int y)
00511 {
00512 Vertex *v = new Vertex((int)floor(scaledX*scaleFactor+0.5), scaledX, QColor(255, 255, 255, y));
00513 if(!containsVertex(v))
00514 {
00515 this->vertices.insert(v);
00516 updateTransferfunction();
00517 }
00518 else
00519 {
00520
00521 }
00522 return v;
00523 }
00524
00525 TransferFunction::Vertex* TransferFunction::addVertex(int scaledX, QColor color)
00526 {
00527 Vertex *v = new Vertex((int)floor(scaledX*scaleFactor+0.5), scaledX, color);
00528 if(!containsVertex(v))
00529 {
00530 this->vertices.insert(v);
00531 updateTransferfunction();
00532 }
00533 else
00534 {
00535
00536 }
00537 return v;
00538
00539 }
00540
00541
00542 void TransferFunction::addVertex(Vertex* v)
00543 {
00544 v->x = ((int)floor(v->xScaled*scaleFactor+0.5));
00545 if(!containsVertex(v))
00546 {
00547 this->vertices.insert(v);
00548 updateTransferfunction();
00549 }
00550 else
00551 {
00552
00553 }
00554 }
00555
00556 void TransferFunction::removeVertex(Vertex* v)
00557 {
00558 if(containsVertex(v) && v->xScaled != 0 && v->x != widthMax)
00559 {
00560 vertices.erase(v);
00561 delete v;
00562 movingVertex = vertices.begin();
00563 updateTransferfunction();
00564 }
00565 }
00566
00567 void TransferFunction::removeAllVertices()
00568 {
00569 for(IteratorVertices iter = vertices.begin(); iter!=vertices.end(); ++iter)
00570 {
00571 delete (*iter);
00572 }
00573 vertices.clear();
00574 }
00575
00576 bool TransferFunction::containsVertex(Vertex *v)
00577 {
00578 return vertices.find(v) != vertices.end();
00579 }
00580
00581 TransferFunction::IteratorVertices TransferFunction::containsNearVertex(Vertex *v)
00582 {
00583 IteratorVertices iterNext = vertices.lower_bound(v);
00584 int margin = floor(Vertex::DRAW_SIZE/2+0.5)+2;
00585
00586 if(((*iterNext)->xScaled - margin) <= v->xScaled)
00587 {
00588 int y1 = v->color.alpha();
00589 int y2 = (*iterNext)->color.alpha();
00590 if(((y2+margin) >= y1) && (y2-margin-1 <= y1))
00591 {
00592 return iterNext;
00593 }
00594 }
00595 iterNext--;
00596 if(((*iterNext)->xScaled + margin+1) >= v->xScaled)
00597 {
00598 int y1 = v->color.alpha();
00599 int y2 = (*iterNext)->color.alpha();
00600 if(((y2+margin) >= y1) && (y2-margin <= y1))
00601 {
00602 return iterNext;
00603 }
00604 }
00605 return IteratorVertices();
00606
00607 }
00608
00609 void TransferFunction::unselectAllVertices()
00610 {
00611 for(IteratorVertices iter = selectedVertices.begin(); iter!=selectedVertices.end(); ++iter)
00612 {
00613 (*iter)->selected = false;
00614 }
00615 selectedVertices.clear();
00616 }
00617
00618 void TransferFunction::unselect(Vertex* v)
00619 {
00620 if(v->selected)
00621 {
00622 v->selected = false;
00623 selectedVertices.erase(v);
00624 }
00625 }
00626
00627 void TransferFunction::select(Vertex *v)
00628 {
00629 selectedVertices.insert(v);
00630 v->selected = true;
00631 }
00632
00633 TransferFunction::Vertex::Vertex()
00634 {
00635 selected = false;
00636 }
00637
00638 TransferFunction::Vertex::Vertex(int x, int xScaled, QColor color)
00639 {
00640 this->x = x;
00641 this->xScaled = xScaled;
00642 this->color = color;
00643 selected = false;
00644 }
00645
00646 void TransferFunction::Vertex::setPos(int x, int xScaled, int y)
00647 {
00648 this->x = x;
00649 this->xScaled = xScaled;
00650 this->color.setAlpha(y);
00651 }
00652
00653 TransferFunction::Vertex::~Vertex()
00654 {
00655 }