1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkCompositeTransferFunctionItem.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 // Hide VTK_DEPRECATED_IN_9_0_0() warnings for this class.
17 #define VTK_DEPRECATION_LEVEL 0
18
19 #include "vtkCompositeTransferFunctionItem.h"
20 #include "vtkAxis.h"
21 #include "vtkCallbackCommand.h"
22 #include "vtkColorTransferFunction.h"
23 #include "vtkCommand.h"
24 #include "vtkImageData.h"
25 #include "vtkObjectFactory.h"
26 #include "vtkPen.h"
27 #include "vtkPiecewiseFunction.h"
28 #include "vtkPointData.h"
29 #include "vtkPoints2D.h"
30
31 // STD includes
32 #include <algorithm>
33 #include <cassert>
34 #include <vector>
35
36 //------------------------------------------------------------------------------
37 vtkStandardNewMacro(vtkCompositeTransferFunctionItem);
38
39 //------------------------------------------------------------------------------
vtkCompositeTransferFunctionItem()40 vtkCompositeTransferFunctionItem::vtkCompositeTransferFunctionItem()
41 {
42 this->PolyLinePen->SetLineType(vtkPen::SOLID_LINE);
43 this->OpacityFunction = nullptr;
44 }
45
46 //------------------------------------------------------------------------------
~vtkCompositeTransferFunctionItem()47 vtkCompositeTransferFunctionItem::~vtkCompositeTransferFunctionItem()
48 {
49 if (this->OpacityFunction)
50 {
51 this->OpacityFunction->RemoveObserver(this->Callback);
52 this->OpacityFunction->Delete();
53 this->OpacityFunction = nullptr;
54 }
55 }
56
57 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)58 void vtkCompositeTransferFunctionItem::PrintSelf(ostream& os, vtkIndent indent)
59 {
60 this->Superclass::PrintSelf(os, indent);
61 os << indent << "CompositeTransferFunction: ";
62 if (this->OpacityFunction)
63 {
64 os << endl;
65 this->OpacityFunction->PrintSelf(os, indent.GetNextIndent());
66 }
67 else
68 {
69 os << "(none)" << endl;
70 }
71 }
72
73 //------------------------------------------------------------------------------
ComputeBounds(double * bounds)74 void vtkCompositeTransferFunctionItem::ComputeBounds(double* bounds)
75 {
76 this->Superclass::ComputeBounds(bounds);
77 if (this->OpacityFunction)
78 {
79 double unused;
80 double opacityRange[2];
81 this->OpacityFunction->GetRange(opacityRange);
82 this->TransformDataToScreen(opacityRange[0], 1, bounds[0], unused);
83 this->TransformDataToScreen(opacityRange[1], 1, bounds[1], unused);
84 }
85 }
86
87 //------------------------------------------------------------------------------
SetOpacityFunction(vtkPiecewiseFunction * opacity)88 void vtkCompositeTransferFunctionItem::SetOpacityFunction(vtkPiecewiseFunction* opacity)
89 {
90 if (opacity == this->OpacityFunction)
91 {
92 return;
93 }
94 if (this->OpacityFunction)
95 {
96 this->OpacityFunction->RemoveObserver(this->Callback);
97 }
98 vtkSetObjectBodyMacro(OpacityFunction, vtkPiecewiseFunction, opacity);
99 if (opacity)
100 {
101 opacity->AddObserver(vtkCommand::ModifiedEvent, this->Callback);
102 }
103 this->ScalarsToColorsModified(this->OpacityFunction, vtkCommand::ModifiedEvent, nullptr);
104 }
105
106 //------------------------------------------------------------------------------
ComputeTexture()107 void vtkCompositeTransferFunctionItem::ComputeTexture()
108 {
109 this->Superclass::ComputeTexture();
110 double screenBounds[4];
111 this->GetBounds(screenBounds);
112 if (screenBounds[0] == screenBounds[1] || !this->OpacityFunction)
113 {
114 return;
115 }
116 if (this->Texture == nullptr)
117 {
118 this->Texture = vtkImageData::New();
119 }
120
121 double dataBounds[4];
122 this->TransformScreenToData(screenBounds[0], screenBounds[2], dataBounds[0], dataBounds[2]);
123 this->TransformScreenToData(screenBounds[1], screenBounds[3], dataBounds[1], dataBounds[3]);
124
125 const bool logX = this->GetXAxis()->GetLogScaleActive();
126 const bool logY = this->GetYAxis()->GetLogScaleActive();
127
128 const int dimension = this->GetTextureWidth();
129 std::vector<double> values(dimension);
130 this->OpacityFunction->GetTable(
131 dataBounds[0], dataBounds[1], dimension, values.data(), 1, logX ? 1 : 0);
132 unsigned char* ptr = reinterpret_cast<unsigned char*>(this->Texture->GetScalarPointer(0, 0, 0));
133
134 // TBD: maybe the shape should be defined somewhere else...
135 if (this->MaskAboveCurve || this->PolyLinePen->GetLineType() != vtkPen::SOLID_LINE)
136 {
137 this->Shape->SetNumberOfPoints(dimension);
138 const double step = (dataBounds[1] - dataBounds[0]) / dimension;
139
140 for (int i = 0; i < dimension; ++i)
141 {
142 if (values[i] < 0. || values[i] > 1.)
143 {
144 vtkWarningMacro(<< "Opacity at point " << i << " is " << values[i]
145 << " which is outside the valid range of [0,1]");
146 }
147 ptr[3] = static_cast<unsigned char>(values[i] * this->Opacity * 255);
148
149 double xValue = dataBounds[0] + step * i;
150 double yValue = values[i];
151 if (logY)
152 {
153 yValue = std::log10(yValue);
154 }
155 this->Shape->SetPoint(i, xValue, yValue);
156 ptr += 4;
157 }
158 }
159 else
160 {
161 for (int i = 0; i < dimension; ++i)
162 {
163 ptr[3] = static_cast<unsigned char>(values[i] * this->Opacity * 255);
164 assert(values[i] <= 1. && values[i] >= 0.);
165 ptr += 4;
166 }
167 }
168 }
169