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 #include "vtkAxis.h"
17 #include "vtkCallbackCommand.h"
18 #include "vtkCommand.h"
19 #include "vtkImageData.h"
20 #include "vtkPiecewiseFunction.h"
21 #include "vtkColorTransferFunction.h"
22 #include "vtkCompositeTransferFunctionItem.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPen.h"
25 #include "vtkPointData.h"
26 #include "vtkPoints2D.h"
27
28 // STD includes
29 #include <algorithm>
30 #include <cassert>
31
32 //-----------------------------------------------------------------------------
33 vtkStandardNewMacro(vtkCompositeTransferFunctionItem);
34
35 //-----------------------------------------------------------------------------
vtkCompositeTransferFunctionItem()36 vtkCompositeTransferFunctionItem::vtkCompositeTransferFunctionItem()
37 {
38 this->PolyLinePen->SetLineType(vtkPen::SOLID_LINE);
39 this->OpacityFunction = nullptr;
40 }
41
42 //-----------------------------------------------------------------------------
~vtkCompositeTransferFunctionItem()43 vtkCompositeTransferFunctionItem::~vtkCompositeTransferFunctionItem()
44 {
45 if (this->OpacityFunction)
46 {
47 this->OpacityFunction->RemoveObserver(this->Callback);
48 this->OpacityFunction->Delete();
49 this->OpacityFunction = nullptr;
50 }
51 }
52
53 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)54 void vtkCompositeTransferFunctionItem::PrintSelf(ostream &os, vtkIndent indent)
55 {
56 this->Superclass::PrintSelf(os, indent);
57 os << indent << "CompositeTransferFunction: ";
58 if (this->OpacityFunction)
59 {
60 os << endl;
61 this->OpacityFunction->PrintSelf(os, indent.GetNextIndent());
62 }
63 else
64 {
65 os << "(none)" << endl;
66 }
67 }
68
69 //-----------------------------------------------------------------------------
ComputeBounds(double * bounds)70 void vtkCompositeTransferFunctionItem::ComputeBounds(double* bounds)
71 {
72 this->Superclass::ComputeBounds(bounds);
73 if (this->OpacityFunction)
74 {
75 double unused;
76 double opacityRange[2];
77 this->OpacityFunction->GetRange(opacityRange);
78 this->TransformDataToScreen(opacityRange[0], 1, bounds[0], unused);
79 this->TransformDataToScreen(opacityRange[1], 1, bounds[1], unused);
80 }
81 }
82
83 //-----------------------------------------------------------------------------
SetOpacityFunction(vtkPiecewiseFunction * opacity)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 vtkSetObjectBodyMacro(OpacityFunction, vtkPiecewiseFunction, opacity);
95 if (opacity)
96 {
97 opacity->AddObserver(vtkCommand::ModifiedEvent, this->Callback);
98 }
99 this->ScalarsToColorsModified(this->OpacityFunction, vtkCommand::ModifiedEvent, nullptr);
100 }
101
102 //-----------------------------------------------------------------------------
ComputeTexture()103 void vtkCompositeTransferFunctionItem::ComputeTexture()
104 {
105 this->Superclass::ComputeTexture();
106 double screenBounds[4];
107 this->GetBounds(screenBounds);
108 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 double dataBounds[4];
119 this->TransformScreenToData(screenBounds[0], screenBounds[2],
120 dataBounds[0], dataBounds[2]);
121 this->TransformScreenToData(screenBounds[1], screenBounds[3],
122 dataBounds[1], dataBounds[3]);
123
124 const bool logX = this->GetXAxis()->GetLogScaleActive();
125 const bool logY = this->GetYAxis()->GetLogScaleActive();
126
127 const int dimension = this->GetTextureWidth();
128 double* values = new double[dimension];
129 this->OpacityFunction->GetTable(dataBounds[0], dataBounds[1],
130 dimension, values, 1,
131 logX ? 1 : 0);
132 unsigned char* ptr =
133 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 ptr[3] = static_cast<unsigned char>(values[i] * this->Opacity * 255);
149
150 double xValue = screenBounds[0] + step * i;
151 double yValue = values[i];
152 if (logY)
153 {
154 yValue = std::log10(yValue);
155 }
156 this->Shape->SetPoint(i, xValue, yValue);
157 ptr+=4;
158 }
159 }
160 else
161 {
162 for (int i = 0; i < dimension; ++i)
163 {
164 ptr[3] = static_cast<unsigned char>(values[i] * this->Opacity * 255);
165 assert(values[i] <= 1. && values[i] >= 0.);
166 ptr+=4;
167 }
168 }
169 delete [] values;
170 }
171