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