Procházet zdrojové kódy

Merge branch 'pieperlocal'

Michi Onken před 15 roky
rodič
revize
bef764417a

+ 2 - 2
LICENSE

@@ -1,4 +1,4 @@
-                                 Apache License
+                                 Indiana License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
 
@@ -200,4 +200,4 @@
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
-   limitations under the License.
+   limitations under the License.

+ 0 - 6
Libs/Core/ctkTransferFunction.cpp

@@ -51,9 +51,3 @@ ctkTransferFunction::~ctkTransferFunction()
   // this->ControlPoints->clear();
   // emit changed();
 }
-
-ctkBezierControlPoint*  ctkTransferFunction::toto()
-{
-  return new ctkBezierControlPoint();
-}
-

+ 9 - 1
Libs/Core/ctkTransferFunction.h

@@ -83,11 +83,13 @@ public:
   
   virtual int count()const = 0;
   virtual bool isDiscrete()const = 0;
+  virtual bool isEditable()const = 0;
 
   inline void range(qreal rangeValues[2])const;
   virtual void range(qreal& minRange, qreal& maxRange)const=0;
   virtual QVariant minValue()const = 0;
   virtual QVariant maxValue()const = 0;
+  inline void valueRange(QVariant range[2])const;
   ///
   virtual int insertControlPoint(const ctkControlPoint& cp) = 0;
   virtual int insertControlPoint(qreal pos) = 0;
@@ -100,7 +102,6 @@ public:
   /// be careful with it, as changing the value might require
   /// more changes to ctkControlPoint.
   virtual void setControlPointValue(int index, const QVariant& value)=0;
-  virtual ctkBezierControlPoint* toto();
 signals:
   void changed();
 };
@@ -118,4 +119,11 @@ void ctkTransferFunction::range(qreal rangeValues[2])const
   this->range(rangeValues[0], rangeValues[1]);
 }
 
+//-----------------------------------------------------------------------------
+void ctkTransferFunction::valueRange(QVariant rangeValues[2])const
+{
+  rangeValues[0] = this->minValue();
+  rangeValues[1] = this->maxValue();
+}
+
 #endif

+ 7 - 0
Libs/Visualization/VTK/Core/ctkVTKColorTransferFunction.cpp

@@ -29,6 +29,7 @@
 #include <vtkColorTransferFunction.h>
 #include <vtkSmartPointer.h>
 
+//-----------------------------------------------------------------------------
 class ctkVTKColorTransferFunctionPrivate: public ctkPrivate<ctkVTKColorTransferFunction>
 {
 public:
@@ -75,6 +76,12 @@ bool ctkVTKColorTransferFunction::isDiscrete()const
 }
 
 //-----------------------------------------------------------------------------
+bool ctkVTKColorTransferFunction::isEditable()const
+{
+  return true;
+}
+
+//-----------------------------------------------------------------------------
 void ctkVTKColorTransferFunction::range(qreal& minRange, qreal& maxRange)const
 {
   CTK_D(const ctkVTKColorTransferFunction);

+ 1 - 0
Libs/Visualization/VTK/Core/ctkVTKColorTransferFunction.h

@@ -47,6 +47,7 @@ public:
   virtual QVariant value(qreal pos)const;
   virtual int count()const;
   virtual bool isDiscrete()const;
+  virtual bool isEditable()const;
 
   virtual void range(qreal& minRange, qreal& maxRange)const;
   virtual QVariant minValue()const;

+ 26 - 8
Libs/Visualization/VTK/Core/ctkVTKLookupTable.cpp

@@ -76,6 +76,12 @@ bool ctkVTKLookupTable::isDiscrete()const
 }
 
 //-----------------------------------------------------------------------------
+bool ctkVTKLookupTable::isEditable()const
+{
+  return true;
+}
+
+//-----------------------------------------------------------------------------
 void ctkVTKLookupTable::range(qreal& minRange, qreal& maxRange)const
 {
   CTK_D(const ctkVTKLookupTable);
@@ -127,12 +133,27 @@ QVariant ctkVTKLookupTable::maxValue()const
 }
 
 //-----------------------------------------------------------------------------
-ctkControlPoint* ctkVTKLookupTable::controlPoint(int index)const
+qreal ctkVTKLookupTable::indexToPos(int index)const
 {
   CTK_D(const ctkVTKLookupTable);
   double* range = d->LookupTable->GetRange();
+  return range[0] + index * ((range[1] - range[0]) / (d->LookupTable->GetNumberOfColors() - 1));
+}
+
+//-----------------------------------------------------------------------------
+int ctkVTKLookupTable::posToIndex(qreal pos)const
+{
+  CTK_D(const ctkVTKLookupTable);
+  double* range = d->LookupTable->GetRange();
+  return (pos - range[0]) / ((range[1] - range[0]) / (d->LookupTable->GetNumberOfColors() - 1));
+}
+
+//-----------------------------------------------------------------------------
+ctkControlPoint* ctkVTKLookupTable::controlPoint(int index)const
+{
+  CTK_D(const ctkVTKLookupTable);
   ctkControlPoint* cp = new ctkControlPoint();
-  cp->P.X = range[0] + index * (range[1] - range[0]) / (d->LookupTable->GetNumberOfColors() - 1);
+  cp->P.X = this->indexToPos(index);
   cp->P.Value = this->value(cp->P.X);
   return cp;
 }
@@ -141,13 +162,10 @@ ctkControlPoint* ctkVTKLookupTable::controlPoint(int index)const
 QVariant ctkVTKLookupTable::value(qreal pos)const
 {
   CTK_D(const ctkVTKLookupTable);
-  Q_ASSERT(d->LookupTable.GetPointer());
-  double rgb[3];
-  d->LookupTable->GetColor(pos, rgb);
-  double alpha = d->LookupTable->GetOpacity(pos);
-  return QColor::fromRgbF(rgb[0], rgb[1], rgb[2], alpha);;
+  QSharedPointer<ctkControlPoint> point = 
+    QSharedPointer<ctkControlPoint>(this->controlPoint(this->posToIndex(pos)));
+  return point->P.Value;
 }
-
 //-----------------------------------------------------------------------------
 int ctkVTKLookupTable::insertControlPoint(const ctkControlPoint& cp)
 {

+ 4 - 0
Libs/Visualization/VTK/Core/ctkVTKLookupTable.h

@@ -46,6 +46,7 @@ public:
   virtual QVariant value(qreal pos)const;
   virtual int count()const;
   virtual bool isDiscrete()const;
+  virtual bool isEditable()const;
 
   virtual void range(qreal& minRange, qreal& maxRange)const;
   virtual QVariant minValue()const;
@@ -59,6 +60,9 @@ public:
 
   void setLookupTable(vtkLookupTable* lookupTable);
   vtkLookupTable* lookupTable()const;
+protected:
+  qreal indexToPos(int index)const;
+  int posToIndex(qreal pos)const;
 private:
   CTK_DECLARE_PRIVATE(ctkVTKLookupTable);
 };

+ 10 - 10
Libs/Visualization/VTK/Core/ctkVTKPiecewiseFunction.cpp

@@ -68,6 +68,12 @@ bool ctkVTKPiecewiseFunction::isDiscrete()const
 }
 
 //-----------------------------------------------------------------------------
+bool ctkVTKPiecewiseFunction::isEditable()const
+{
+  return true;
+}
+
+//-----------------------------------------------------------------------------
 void ctkVTKPiecewiseFunction::range(qreal& minRange, qreal& maxRange)const
 {
   CTK_D(const ctkVTKPiecewiseFunction);
@@ -95,15 +101,12 @@ QVariant ctkVTKPiecewiseFunction::minValue()const
     }
   //Initialize to max value
   /// TODO initialize with max value
-  double minValue = 9999.99;
+  double minValue = VTK_DOUBLE_MAX;
   for (int i = 0; i < this->count(); ++i)
     {
     double value[4];
     d->PiecewiseFunction->GetNodeValue(i, value);
-    if ( value[1] < minValue)
-      {
-      minValue = value[1];
-      }
+    minValue = qMin(value[1], minValue);
     }
   return minValue;
 }
@@ -119,15 +122,12 @@ QVariant ctkVTKPiecewiseFunction::maxValue()const
     }
   //Initialize to max value
   /// TODO initialize with max value
-  qreal maxValue = 0.;
+  qreal maxValue = VTK_DOUBLE_MIN;
   for (int i = 0; i < this->count(); ++i)
     {
     double value[4];
     d->PiecewiseFunction->GetNodeValue(i, value);
-    if ( maxValue < value[1])
-      {
-      maxValue = value[1];
-      }
+    maxValue = qMax(maxValue, value[1]);
     }
   return maxValue;
 }

+ 1 - 0
Libs/Visualization/VTK/Core/ctkVTKPiecewiseFunction.h

@@ -46,6 +46,7 @@ public:
   virtual QVariant value(qreal pos)const;
   virtual int count()const;
   virtual bool isDiscrete()const;
+  virtual bool isEditable()const;
 
   virtual void range(qreal& minRange, qreal& maxRange)const;
   virtual QVariant minValue()const;

+ 3 - 0
Libs/Widgets/CMakeLists.txt

@@ -64,6 +64,8 @@ SET(KIT_SRCS
   ctkTransferFunctionItem.h
   ctkTransferFunctionWidget.cpp
   ctkTransferFunctionWidget.h
+  ctkTransferFunctionScene.cpp
+  ctkTransferFunctionScene.h
   ctkTreeComboBox.cpp
   ctkTreeComboBox.h
   )
@@ -97,6 +99,7 @@ SET(KIT_MOC_SRCS
   ctkTransferFunctionItem.h
   ctkTransferFunctionControlPointsItem.h
   ctkTransferFunctionWidget.h
+  ctkTransferFunctionScene.h
   ctkTreeComboBox.h
   )
 

+ 11 - 66
Libs/Widgets/ctkTransferFunctionControlPointsItem.cpp

@@ -28,8 +28,8 @@
 #include <QVariant>
 
 /// CTK includes
-#include "ctkTransferFunction.h"
 #include "ctkTransferFunctionControlPointsItem.h"
+#include "ctkTransferFunctionScene.h"
 
 //-----------------------------------------------------------------------------
 class ctkTransferFunctionControlPointsItemPrivate: 
@@ -46,7 +46,7 @@ public:
 //-----------------------------------------------------------------------------
 ctkTransferFunctionControlPointsItemPrivate::ctkTransferFunctionControlPointsItemPrivate()
 {
-  this->PointSize = QSizeF(10.,10.);
+  this->PointSize = QSizeF(0.01,0.01);
   this->SelectedPoint = -1;
 }
 
@@ -90,74 +90,19 @@ void ctkTransferFunctionControlPointsItem::paint(
     return;
     }
 
-  qreal rangeXDiff = this->rangeXDiff();
-  qreal rangeXOffSet = this->rangeXOffSet();
-
-  qreal rangeYDiff = this->rangeYDiff();
-  qreal rangeYOffSet = this->rangeYDiff();
-
-  ctkControlPoint* startCP = this->transferFunction()->controlPoint(0);
-  ctkControlPoint* endCP = 0;
-  qreal start = 0;
-  qreal end = 0;
-
-  QPainterPath path;
- // this->x(controlpoint)
-  QPointF startPos(startCP->x() - rangeXOffSet, this->y(startCP->value()) - rangeYOffSet);
-  startPos.rx() *= rangeXDiff;
-  startPos.setY(this->rect().height() 
-                - startPos.y() * rangeYDiff);
+  ctkTransferFunctionScene* tfScene = dynamic_cast<ctkTransferFunctionScene*>(this->scene());
+  Q_ASSERT(tfScene);
   
-  d->ControlPoints.clear();
-  d->ControlPoints << startPos;
-
-  path.moveTo(startPos);
-  for(int i = 1; i < count; ++i)
-    {
-    endCP = this->transferFunction()->controlPoint(i);
-    if (dynamic_cast<ctkNonLinearControlPoint*>(startCP))
-      {
-      QList<ctkPoint> points = this->nonLinearPoints(startCP, endCP);
-      int j;
-      for (j = 1; j < points.count(); ++j)
-        {
-        path.lineTo(
-          QPointF(
-            this->transferFunction2ScreenCoordinates(points[j].X,
-                                                     this->y(points[j].Value))));
-        }
-      j = points.count() - 1;
-      d->ControlPoints << QPointF( this->transferFunction2ScreenCoordinates(
-        points[j].X,
-        this->y(points[j].Value)));
-      }
-    else //dynamic_cast<ctkBezierControlPoint*>(startCP))
-      {
-      QList<ctkPoint> points = this->bezierParams(startCP, endCP);
-      QList<ctkPoint>::iterator it = points.begin();
-      QList<QPointF> bezierPoints;
-      foreach(const ctkPoint& p, points)
-        {
-        bezierPoints << 
-          QPointF((p.X - rangeXOffSet)* rangeXDiff , 
-                  this->rect().height() - (this->y(p.Value) - rangeYOffSet)* rangeYDiff);
-        }
-      path.cubicTo(bezierPoints[1], bezierPoints[2], bezierPoints[3]);
-      d->ControlPoints << bezierPoints[3];
-      }
-    //qDebug() << i << points[0] << points[1] << points[2] << points[3];
-    delete startCP;
-    startCP = endCP;
-    }
-  if (startCP)
-    {
-    delete startCP;
-    }
+  const QPainterPath& curve = tfScene->curve();
   painter->setRenderHint(QPainter::Antialiasing);
-  painter->setPen(QPen(QColor(255, 255, 255, 191), 1));
-  painter->drawPath(path);
+  QPen pen(QColor(255, 255, 255, 191), 1);
+  pen.setCosmetic(true);
+  painter->setPen(pen);
+  painter->drawPath(curve);
 
+  d->ControlPoints = tfScene->points();
   QPainterPath points;
+  points.setFillRule(Qt::WindingFill);
   foreach(const QPointF& point, d->ControlPoints)
     {
     points.addEllipse(point, d->PointSize.width(), d->PointSize.height());

+ 10 - 14
Libs/Widgets/ctkTransferFunctionItem.cpp

@@ -37,7 +37,7 @@ class ctkTransferFunctionItemPrivate :
 {
 public:
   ctkTransferFunctionItemPrivate();
-
+  void init();
   QRectF               Rect;
   ctkTransferFunction* TransferFunction;
 };
@@ -46,6 +46,13 @@ public:
 ctkTransferFunctionItemPrivate::ctkTransferFunctionItemPrivate()
 {
   this->TransferFunction = 0;
+  this->Rect = QRectF(0.,0.,1.,1.);
+}
+
+//-----------------------------------------------------------------------------
+void ctkTransferFunctionItemPrivate::init()
+{
+  CTK_P(ctkTransferFunctionItem);
 }
 
 //-----------------------------------------------------------------------------
@@ -53,6 +60,7 @@ ctkTransferFunctionItem::ctkTransferFunctionItem(QGraphicsItem* parentGraphicsIt
   :QGraphicsObject(parentGraphicsItem)
 {
   CTK_INIT_PRIVATE(ctkTransferFunctionItem);
+  ctk_d()->init();
 }
 
 //-----------------------------------------------------------------------------
@@ -61,6 +69,7 @@ ctkTransferFunctionItem::ctkTransferFunctionItem(
   :QGraphicsObject(parentItem)
 {
   CTK_INIT_PRIVATE(ctkTransferFunctionItem);
+  ctk_d()->init();
   this->setTransferFunction(transferFunction);
 }
 
@@ -74,14 +83,7 @@ ctkTransferFunctionItem::~ctkTransferFunctionItem()
 void ctkTransferFunctionItem::setTransferFunction(ctkTransferFunction* transferFunction)
 {
   CTK_D(ctkTransferFunctionItem);
-  if (d->TransferFunction == transferFunction)
-    {
-    return;
-    }
   d->TransferFunction = transferFunction;
-  connect(d->TransferFunction, SIGNAL(changed()),
-          this, SLOT(onTransferFunctionChanged()));
-  this->update();
 }
 
 //-----------------------------------------------------------------------------
@@ -92,12 +94,6 @@ ctkTransferFunction* ctkTransferFunctionItem::transferFunction() const
 }
 
 //-----------------------------------------------------------------------------
-void ctkTransferFunctionItem::onTransferFunctionChanged()
-{
-  this->update();
-}
-
-//-----------------------------------------------------------------------------
 void ctkTransferFunctionItem::setRect(const QRectF& newRect)
 {
   CTK_D(ctkTransferFunctionItem);

+ 1 - 2
Libs/Widgets/ctkTransferFunctionItem.h

@@ -69,8 +69,7 @@ protected:
 
   QList<ctkPoint> bezierParams(ctkControlPoint* start, ctkControlPoint* end)const;
   QList<ctkPoint> nonLinearPoints(ctkControlPoint* start, ctkControlPoint* end)const;
-protected slots:
-  virtual void onTransferFunctionChanged();
+
 private:
   CTK_DECLARE_PRIVATE(ctkTransferFunctionItem);
 };

+ 362 - 0
Libs/Widgets/ctkTransferFunctionScene.cpp

@@ -0,0 +1,362 @@
+/*=========================================================================
+
+  Library:   CTK
+ 
+  Copyright (c) 2010  Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ 
+=========================================================================*/
+/// Qt includes
+#include <QGraphicsScene>
+#include <QResizeEvent>
+#include <QDebug>
+
+/// CTK includes
+#include "ctkTransferFunction.h"
+#include "ctkTransferFunctionScene.h"
+
+//-----------------------------------------------------------------------------
+class ctkTransferFunctionScenePrivate: public ctkPrivate<ctkTransferFunctionScene>
+{
+  CTK_DECLARE_PUBLIC(ctkTransferFunctionScene);
+public:
+  ctkTransferFunctionScenePrivate();
+  QRectF               OldRect;
+  ctkTransferFunction* TransferFunction;
+  QPainterPath   Path;
+  QList<QPointF> Points;
+  qreal        WorldRangeX[2];
+  QVariant     WorldRangeY[2];
+  qreal        RangeXDiff;
+  qreal        RangeXOffSet;
+  qreal        RangeYDiff;
+  qreal        RangeYOffSet;
+};
+
+ctkTransferFunctionScenePrivate::ctkTransferFunctionScenePrivate()
+{
+  this->TransferFunction = 0;
+}
+
+//-----------------------------------------------------------------------------
+ctkTransferFunctionScene::ctkTransferFunctionScene(QObject* parentObject)
+  :QGraphicsScene(parentObject)
+{
+  CTK_INIT_PRIVATE(ctkTransferFunctionScene);
+}
+
+//-----------------------------------------------------------------------------
+ctkTransferFunctionScene::ctkTransferFunctionScene(
+  ctkTransferFunction* transferFunction, QObject* parentObject)
+  :QGraphicsScene(parentObject)
+{
+  CTK_INIT_PRIVATE(ctkTransferFunctionScene);
+  this->setTransferFunction(transferFunction);
+}
+//-----------------------------------------------------------------------------
+ctkTransferFunctionScene::~ctkTransferFunctionScene()
+{
+}
+
+//-----------------------------------------------------------------------------
+void ctkTransferFunctionScene::setTransferFunction(ctkTransferFunction* transferFunction)
+{
+  CTK_D(ctkTransferFunctionScene);
+  if (d->TransferFunction == transferFunction)
+    {
+    return;
+    }
+  d->TransferFunction = transferFunction;
+  connect( d->TransferFunction, SIGNAL(changed()),
+           this, SLOT(onTransferFunctionChanged()),
+           Qt::UniqueConnection);
+  this->update();
+}
+
+//-----------------------------------------------------------------------------
+ctkTransferFunction* ctkTransferFunctionScene::transferFunction()const
+{
+  return ctk_d()->TransferFunction;
+}
+
+//-----------------------------------------------------------------------------
+void ctkTransferFunctionScene::onTransferFunctionChanged()
+{
+  CTK_D(ctkTransferFunctionScene);
+  // TODO delete cache here
+  d->Path = QPainterPath();
+  this->update();  
+}
+
+//-----------------------------------------------------------------------------
+const QPainterPath& ctkTransferFunctionScene::curve()const
+{
+  CTK_D(const ctkTransferFunctionScene);
+  if (d->Path.isEmpty())// || this->sceneRect() != d->OldRect)
+    {
+    const_cast<ctkTransferFunctionScene*>(this)->computeCurve();
+    }
+  return d->Path;
+}
+
+//-----------------------------------------------------------------------------
+const QList<QPointF>& ctkTransferFunctionScene::points()const
+{
+  CTK_D(const ctkTransferFunctionScene);
+  if (d->Path.isEmpty())// || this->sceneRect() != d->OldRect)
+    {
+    const_cast<ctkTransferFunctionScene*>(this)->computeCurve();
+    }
+  return d->Points;
+}
+
+//-----------------------------------------------------------------------------
+void ctkTransferFunctionScene::computeCurve()
+{
+  CTK_D(ctkTransferFunctionScene);
+
+  int count = d->TransferFunction ? d->TransferFunction->count() : 0;
+  if (count <= 0)
+    {
+    return;
+    }
+  qDebug() << "computeCurve" << this->sceneRect();
+  d->TransferFunction->range(d->WorldRangeX[0], d->WorldRangeX[1]);
+  d->WorldRangeY[0] = this->y(d->TransferFunction->minValue());
+  d->WorldRangeY[1] = this->y(d->TransferFunction->maxValue());
+
+  d->RangeXDiff   = this->computeRangeXDiff(this->sceneRect(), d->WorldRangeX);
+  d->RangeXOffSet = this->computeRangeXOffset(d->WorldRangeX);
+
+  d->RangeYDiff   = this->computeRangeYDiff(this->sceneRect(), d->WorldRangeY);
+  d->RangeYOffSet = this->computeRangeYOffset(d->WorldRangeY);
+
+  ctkControlPoint* startCP = d->TransferFunction->controlPoint(0);
+  ctkControlPoint* nextCP = 0;
+
+  QPointF startPos = this->mapPointToScreen(startCP);
+  
+  d->Points.clear();
+  d->Points << startPos;
+
+  d->Path = QPainterPath();
+  d->Path.moveTo(startPos);
+  for(int i = 1; i < count; ++i)
+    {
+    nextCP = d->TransferFunction->controlPoint(i);
+    if (dynamic_cast<ctkNonLinearControlPoint*>(startCP))
+      {
+      QList<ctkPoint> points = this->nonLinearPoints(startCP, nextCP);
+      int j;
+      for (j = 1; j < points.count(); ++j)
+        {
+        d->Path.lineTo(this->mapPointToScreen(points[j]));
+        }
+      j = points.count() - 1;
+      d->Points << this->mapPointToScreen(points[j]);
+      }
+    else //dynamic_cast<ctkBezierControlPoint*>(startCP))
+      {
+      QList<ctkPoint> points = this->bezierParams(startCP, nextCP);
+      QList<ctkPoint>::iterator it = points.begin();
+      QList<QPointF> bezierPoints;
+      foreach(const ctkPoint& p, points)
+        {
+        bezierPoints << this->mapPointToScreen(p);
+        }
+      d->Path.cubicTo(bezierPoints[1], bezierPoints[2], bezierPoints[3]);
+      d->Points << bezierPoints[3];
+      }
+    //qDebug() << i << points[0] << points[1] << points[2] << points[3];
+    delete startCP;
+    startCP = nextCP;
+    }
+  if (startCP)
+    {
+    delete startCP;
+    }
+}
+
+//-----------------------------------------------------------------------------
+QList<ctkPoint> ctkTransferFunctionScene::bezierParams(
+  ctkControlPoint* start, ctkControlPoint* end) const
+{
+  Q_ASSERT(start);
+  Q_ASSERT(end);
+  QList<ctkPoint> points; 
+  
+  ctkBezierControlPoint* bezierCP = dynamic_cast<ctkBezierControlPoint*>(start);
+  if (!bezierCP)
+    {// just duplicate start and end into p1 and p2
+    points << start->P;
+    points << start->P;
+    points << end->P;
+    points << end->P;
+    return points;
+    }
+  
+  points << start->P;
+  points << bezierCP->P1;
+  points << bezierCP->P2;
+  points << end->P;
+  return points;
+}
+
+//-----------------------------------------------------------------------------
+QList<ctkPoint> ctkTransferFunctionScene::nonLinearPoints(
+  ctkControlPoint* start, ctkControlPoint* end) const
+{
+  Q_ASSERT(start);
+    
+  ctkNonLinearControlPoint* nonLinearCP = 
+    dynamic_cast<ctkNonLinearControlPoint*>(start);
+  if (!nonLinearCP)
+    {
+    QList<ctkPoint> points; 
+    points << start->P;
+    points << end->P;
+    return points;
+    }
+  return nonLinearCP->SubPoints;
+}
+
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::y(const QVariant& v) const
+{ 
+  Q_ASSERT(v.canConvert<qreal>() || v.canConvert<QColor>());
+  if (v.canConvert<QColor>())
+    {
+    return v.value<QColor>().alphaF();
+    }
+  return v.toReal();
+}
+
+//-----------------------------------------------------------------------------
+QColor ctkTransferFunctionScene::color(const QVariant& v) const
+{ 
+  //Q_ASSERT(v.canConvert<QColor>());
+  if (v.canConvert<QColor>())
+    {
+    return v.value<QColor>();
+    }
+  else
+    {
+    //black background
+    QColor defaultColor(0., 0., 0.);
+    return defaultColor;
+    }
+  return QColor();
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::computeRangeXDiff(const QRectF& rect, qreal rangeX[2])
+{
+  return rect.width() / (rangeX[1] - rangeX[0]);
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::computeRangeXOffset(qreal rangeX[2])
+{
+  return rangeX[0];
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::computeRangeYDiff(const QRectF& rect, const QVariant rangeY[2])
+{
+  qreal rangeYDiff = rect.height();
+  qreal rangePosY[2];
+  rangePosY[0] = this->posY(rangeY[0]);
+  rangePosY[1] = this->posY(rangeY[1]);
+  if (rangePosY[1] == rangePosY[0])
+    {
+    rangeYDiff /= rangePosY[0];
+    return rangeYDiff;
+    }
+  rangeYDiff /= rangePosY[1] - rangePosY[0];
+  return rangeYDiff;
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::computeRangeYOffset(const QVariant rangeY[2])
+{
+  qreal rangePosY[2];
+  rangePosY[0] = this->posY(rangeY[0]);
+  rangePosY[1] = this->posY(rangeY[1]);
+
+  if (rangePosY[1] == rangePosY[0])
+    {
+    return 0.;
+    }
+  return rangePosY[0];
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::posX(const qreal& x)const
+{
+  return x;
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::posY(const QVariant& value)const
+{
+  Q_ASSERT(value.canConvert<qreal>() || value.canConvert<QColor>());
+  if (value.canConvert<QColor>())
+    {
+    return value.value<QColor>().alphaF();
+    }
+  return value.toReal();
+}
+
+//-----------------------------------------------------------------------------
+QPointF ctkTransferFunctionScene::mapPointToScreen(const ctkControlPoint* cp)const
+{
+  return QPointF(this->mapXToScreen(this->posX(cp->x())),
+                 this->mapYToScreen(this->posY(cp->value())));
+}
+
+//-----------------------------------------------------------------------------
+QPointF ctkTransferFunctionScene::mapPointToScreen(const ctkPoint& point)const
+{
+  return QPointF( this->mapXToScreen(this->posX(point.X)),
+                  this->mapYToScreen(this->posY(point.Value)));
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::mapXToScreen(qreal xPos)const
+{
+  CTK_D(const ctkTransferFunctionScene);
+  return (xPos - d->RangeXOffSet) * d->RangeXDiff;
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::mapYToScreen(qreal yPos)const
+{
+  CTK_D(const ctkTransferFunctionScene);
+  return this->height() - (yPos - d->RangeYOffSet) * d->RangeYDiff;
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::mapXFromScreen(qreal screenPosX)const
+{
+  CTK_D(const ctkTransferFunctionScene);
+  return (screenPosX / d->RangeXDiff) + d->RangeXOffSet;
+}
+
+//-----------------------------------------------------------------------------
+qreal ctkTransferFunctionScene::mapYFromScreen(qreal screenPosY)const
+{
+  CTK_D(const ctkTransferFunctionScene);
+  return ((this->height() - screenPosY) / d->RangeYDiff) + d->RangeYOffSet ;
+}

+ 81 - 0
Libs/Widgets/ctkTransferFunctionScene.h

@@ -0,0 +1,81 @@
+/*=========================================================================
+
+  Library:   CTK
+ 
+  Copyright (c) 2010  Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ 
+=========================================================================*/
+
+#ifndef __ctkTransferFunctionScene_h
+#define __ctkTransferFunctionScene_h
+
+/// Qt includes
+#include <QGraphicsScene>
+
+/// CTK includes
+#include "CTKWidgetsExport.h"
+#include "ctkPimpl.h"
+
+class ctkTransferFunction;
+class ctkTransferFunctionScenePrivate;
+class ctkControlPoint;
+class ctkPoint;
+
+//-----------------------------------------------------------------------------
+class CTK_WIDGETS_EXPORT ctkTransferFunctionScene: public QGraphicsScene
+{
+  Q_OBJECT;
+public:
+  ctkTransferFunctionScene(QObject* parent = 0);
+  ctkTransferFunctionScene(ctkTransferFunction* transferFunction, QObject* parent = 0);
+  virtual ~ctkTransferFunctionScene();
+
+  void setTransferFunction(ctkTransferFunction* transferFunction);
+  ctkTransferFunction* transferFunction()const;
+
+  qreal y(const QVariant& v) const;
+  QColor color(const QVariant& v) const;
+
+  qreal posX(const qreal& x)const;
+  qreal posY(const QVariant& value)const;
+  
+  QPointF mapPointToScreen(const ctkControlPoint* cp)const;
+  QPointF mapPointToScreen(const ctkPoint& point)const;
+ 
+  qreal mapXToScreen(qreal posX)const;
+  qreal mapYToScreen(qreal posY)const;
+  qreal mapXFromScreen(qreal screenPosX)const;
+  qreal mapYFromScreen(qreal screenPosY)const;
+
+  QList<ctkPoint> bezierParams(ctkControlPoint* start, ctkControlPoint* end) const;
+  QList<ctkPoint> nonLinearPoints(ctkControlPoint* start, ctkControlPoint* end) const;
+
+  const QPainterPath& curve()const;
+  const QList<QPointF>& points()const;
+  void computeCurve();
+
+protected slots:
+  virtual void onTransferFunctionChanged();
+
+protected:
+  qreal computeRangeXDiff(const QRectF& rect, qreal rangeX[2]);
+  qreal computeRangeXOffset(qreal rangeX[2]);
+  qreal computeRangeYDiff(const QRectF& rect, const QVariant rangeY[2]);
+  qreal computeRangeYOffset(const QVariant rangeY[2]);
+private:
+  CTK_DECLARE_PRIVATE(ctkTransferFunctionScene);
+};
+
+#endif

+ 28 - 9
Libs/Widgets/ctkTransferFunctionWidget.cpp

@@ -18,14 +18,15 @@
  
 =========================================================================*/
 /// Qt includes
+#include <QDebug>
+//#include <QGLWidget>
 #include <QGraphicsScene>
 #include <QResizeEvent>
-#include <QDebug>
 
 /// CTK includes
 #include "ctkTransferFunction.h"
 #include "ctkTransferFunctionWidget.h"
-#include "ctkTransferFunctionItem.h"
+#include "ctkTransferFunctionScene.h"
 #include "ctkTransferFunctionGradientItem.h"
 #include "ctkTransferFunctionControlPointsItem.h"
 
@@ -34,17 +35,25 @@ class ctkTransferFunctionWidgetPrivate: public ctkPrivate<ctkTransferFunctionWid
 {
   CTK_DECLARE_PUBLIC(ctkTransferFunctionWidget);
 public:
+  ctkTransferFunctionWidgetPrivate();
   void init();
   ctkTransferFunction* TransferFunction;
 };
 
 //-----------------------------------------------------------------------------
+ctkTransferFunctionWidgetPrivate::ctkTransferFunctionWidgetPrivate()
+{
+  this->TransferFunction = 0;
+}
+
+//-----------------------------------------------------------------------------
 void ctkTransferFunctionWidgetPrivate::init()
 {
   CTK_P(ctkTransferFunctionWidget);
-  p->setScene(new QGraphicsScene(p));
+  p->setScene(new ctkTransferFunctionScene(p));
   p->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
   p->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  //p->setViewport(new QGLWidget);
 }
 
 //-----------------------------------------------------------------------------
@@ -74,15 +83,19 @@ void ctkTransferFunctionWidget::setTransferFunction(ctkTransferFunction* transfe
 {
   CTK_D(ctkTransferFunctionWidget);
   d->TransferFunction = transferFunction;
-  Q_ASSERT(this->scene());
-  this->scene()->clear();
+  ctkTransferFunctionScene* tfScene = dynamic_cast<ctkTransferFunctionScene*>(this->scene());
+  Q_ASSERT(tfScene);
+  tfScene->clear();
+  tfScene->setTransferFunction(transferFunction);
+
   ctkTransferFunctionGradientItem* gradient = 
     new ctkTransferFunctionGradientItem(transferFunction);
-  gradient->setRect(0, 0, this->width(), this->height());
+  //gradient->setRect(tfScene->sceneRect());
   this->scene()->addItem(gradient);
+
   ctkTransferFunctionControlPointsItem* controlPoints = 
     new ctkTransferFunctionControlPointsItem(transferFunction);
-  controlPoints->setRect(0, 0, this->width(), this->height());
+  //controlPoints->setRect(tfScene->sceneRect());
   this->scene()->addItem(controlPoints);
 }
 
@@ -95,7 +108,9 @@ ctkTransferFunction* ctkTransferFunctionWidget::transferFunction()const
 //-----------------------------------------------------------------------------
 void ctkTransferFunctionWidget::resizeEvent(QResizeEvent * event)
 {
+  /*
   QRectF sceneRect(QPointF(0,0),event->size());
+  this->scene()->setSceneRect(sceneRect);
   foreach(QGraphicsItem * item, this->scene()->items())
     {
     ctkTransferFunctionItem* rectItem = 
@@ -105,8 +120,12 @@ void ctkTransferFunctionWidget::resizeEvent(QResizeEvent * event)
       rectItem->setRect(sceneRect);
       }
     }
-  this->scene()->setSceneRect(sceneRect);
-  
+  */
+  QMatrix zoomMatrix;
+  zoomMatrix.scale(event->size().width(), event->size().height());
+  bool blocked = this->blockSignals(true);
+  this->setMatrix(zoomMatrix);
+  this->blockSignals(blocked);
   this->QGraphicsView::resizeEvent(event);
   // Control points are resized by the view transform, we want
   // fixed size control points, lines...