vtkCompositeTransferFunctionItem.cxx 5.27 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCompositeTransferFunctionItem.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

16
#include "vtkAxis.h"
17 18
#include "vtkCallbackCommand.h"
#include "vtkCommand.h"
19 20
#include "vtkImageData.h"
#include "vtkPiecewiseFunction.h"
21
#include "vtkColorTransferFunction.h"
22 23
#include "vtkCompositeTransferFunctionItem.h"
#include "vtkObjectFactory.h"
24
#include "vtkPen.h"
25
#include "vtkPointData.h"
26
#include "vtkPoints2D.h"
27

28 29
// STD includes
#include <algorithm>
30 31 32 33 34 35 36 37
#include <cassert>

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkCompositeTransferFunctionItem);

//-----------------------------------------------------------------------------
vtkCompositeTransferFunctionItem::vtkCompositeTransferFunctionItem()
{
38
  this->PolyLinePen->SetLineType(vtkPen::SOLID_LINE);
39
  this->OpacityFunction = nullptr;
40 41 42 43 44 45
}

//-----------------------------------------------------------------------------
vtkCompositeTransferFunctionItem::~vtkCompositeTransferFunctionItem()
{
  if (this->OpacityFunction)
46
  {
47
    this->OpacityFunction->RemoveObserver(this->Callback);
48
    this->OpacityFunction->Delete();
49
    this->OpacityFunction = nullptr;
50
  }
51 52 53 54 55 56 57 58
}

//-----------------------------------------------------------------------------
void vtkCompositeTransferFunctionItem::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "CompositeTransferFunction: ";
  if (this->OpacityFunction)
59
  {
60 61
    os << endl;
    this->OpacityFunction->PrintSelf(os, indent.GetNextIndent());
62
  }
63
  else
64
  {
65
    os << "(none)" << endl;
66
  }
67 68 69
}

//-----------------------------------------------------------------------------
70
void vtkCompositeTransferFunctionItem::ComputeBounds(double* bounds)
71
{
72
  this->Superclass::ComputeBounds(bounds);
73
  if (this->OpacityFunction)
74
  {
75 76 77 78 79
    double unused;
    double opacityRange[2];
    this->OpacityFunction->GetRange(opacityRange);
    this->TransformDataToScreen(opacityRange[0], 1, bounds[0], unused);
    this->TransformDataToScreen(opacityRange[1], 1, bounds[1], unused);
80
  }
81 82
}

83
//-----------------------------------------------------------------------------
84
void vtkCompositeTransferFunctionItem::SetOpacityFunction(vtkPiecewiseFunction* opacity)
85
{
86
  if (opacity == this->OpacityFunction)
87
  {
88
    return;
89
  }
90
  if (this->OpacityFunction)
91
  {
92
    this->OpacityFunction->RemoveObserver(this->Callback);
93
  }
94 95
  vtkSetObjectBodyMacro(OpacityFunction, vtkPiecewiseFunction, opacity);
  if (opacity)
96
  {
97
    opacity->AddObserver(vtkCommand::ModifiedEvent, this->Callback);
98
  }
99
  this->ScalarsToColorsModified(this->OpacityFunction, vtkCommand::ModifiedEvent, nullptr);
100 101
}

102 103 104 105
//-----------------------------------------------------------------------------
void vtkCompositeTransferFunctionItem::ComputeTexture()
{
  this->Superclass::ComputeTexture();
106 107 108
  double screenBounds[4];
  this->GetBounds(screenBounds);
  if (screenBounds[0] == screenBounds[1]
109
      || !this->OpacityFunction)
110
  {
111
    return;
112
  }
113
  if (this->Texture == nullptr)
114
  {
115
    this->Texture = vtkImageData::New();
116
  }
117

118 119 120 121 122 123
  double dataBounds[4];
  this->TransformScreenToData(screenBounds[0], screenBounds[2],
                              dataBounds[0], dataBounds[2]);
  this->TransformScreenToData(screenBounds[1], screenBounds[3],
                              dataBounds[1], dataBounds[3]);

124 125 126
  const bool logX = this->GetXAxis()->GetLogScaleActive();
  const bool logY = this->GetYAxis()->GetLogScaleActive();

127
  const int dimension = this->GetTextureWidth();
128
  double* values = new double[dimension];
129 130
  this->OpacityFunction->GetTable(dataBounds[0], dataBounds[1],
                                  dimension, values, 1,
131
                                  logX ? 1 : 0);
132 133
  unsigned char* ptr =
    reinterpret_cast<unsigned char*>(this->Texture->GetScalarPointer(0,0,0));
134

135
  // TBD: maybe the shape should be defined somewhere else...
136
  if (this->MaskAboveCurve || this->PolyLinePen->GetLineType() != vtkPen::SOLID_LINE)
137
  {
138
    this->Shape->SetNumberOfPoints(dimension);
139
    const double step = (screenBounds[1] - screenBounds[0]) / dimension;
140

141
    for (int i = 0; i < dimension; ++i)
142
    {
143
      if (values[i] < 0. || values[i] > 1.)
144
      {
145
        vtkWarningMacro( << "Opacity at point " << i << " is " << values[i]
146
                         << " which is outside the valid range of [0,1]");
147
      }
148 149
      ptr[3] = static_cast<unsigned char>(values[i] * this->Opacity * 255);

150
      double xValue = screenBounds[0] + step * i;
151 152 153 154 155 156
      double yValue = values[i];
      if (logY)
      {
        yValue = std::log10(yValue);
      }
      this->Shape->SetPoint(i, xValue, yValue);
157 158
      ptr+=4;
    }
159
  }
160
  else
161
  {
162
    for (int i = 0; i < dimension; ++i)
163
    {
164 165 166
      ptr[3] = static_cast<unsigned char>(values[i] * this->Opacity * 255);
      assert(values[i] <= 1. && values[i] >= 0.);
      ptr+=4;
167
    }
168
  }
169
  delete [] values;
170
}