1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    TestLookupTable.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 // Test some generic features of vtkLookupTable
16 
17 #include "vtkLookupTable.h"
18 #include "vtkMath.h"
19 #include "vtkMathUtilities.h"
20 #include "vtkCommand.h"
21 #include "vtkSmartPointer.h"
22 
23 // simple macro for performing tests
24 #define TestAssert(t) \
25 if (!(t)) \
26 { \
27   cerr << "In " << __FILE__ << ":"; \
28   cerr << " Test assertion failed line " << __LINE__ << ": " << #t << "\n"; \
29   rval |= 1; \
30 }
31 
32 #define TestVector4d(t1, t2)                                        \
33   TestAssert(                                                       \
34     (vtkMathUtilities::FuzzyCompare<double>(t1[0], t2[0])           \
35      && vtkMathUtilities::FuzzyCompare<double>(t1[1], t2[1])        \
36      && vtkMathUtilities::FuzzyCompare<double>(t1[2], t2[2])        \
37      && vtkMathUtilities::FuzzyCompare<double>(t1[3], t2[3])))
38 
TestColor4uc(const unsigned char * expected,const unsigned char * test)39 int TestColor4uc(const unsigned char* expected, const unsigned char* test)
40 {
41   int failed = expected[0] != test[0] || expected[1] != test[1] ||
42     expected[2] != test[2] || expected[3] != test[3] ? 1 : 0;
43   if (failed)
44   {
45     std::cerr << "Expected color: " <<
46       static_cast<int>(expected[0]) << ", " <<
47       static_cast<int>(expected[1]) << ", " <<
48       static_cast<int>(expected[2]) << ", " <<
49       static_cast<int>(expected[3]) << std::endl;
50     std::cerr << "Test color: " <<
51       static_cast<int>(test[0]) << ", " <<
52       static_cast<int>(test[1]) << ", " <<
53       static_cast<int>(test[2]) << ", " <<
54       static_cast<int>(test[3]) << std::endl;
55   }
56 
57   return !failed;
58 }
59 
60 // a simple error observer
61 namespace {
62 
63 class errorObserver
64 {
65 public:
errorObserver()66   errorObserver() : EventId(0) {}
67 
Reset()68   void Reset() { this->EventId = 0; }
69 
GetEvent() const70   unsigned long GetEvent() const { return this->EventId; }
71 
Callback(vtkObject *,unsigned long e,void *)72   void Callback(vtkObject *, unsigned long e, void *) {
73     this->EventId = e; }
74 
75 private:
76   unsigned long EventId;
77 };
78 
79 }
80 
TestLookupTable(int,char * [])81 int TestLookupTable(int,char *[])
82 {
83   int rval = 0;
84 
85   vtkSmartPointer<vtkLookupTable> table =
86     vtkSmartPointer<vtkLookupTable>::New();
87 
88   // == check computation of table index ==
89 
90   // basic mapping test
91   double lo = 3.234;
92   double hi = 6.123;
93   double tol = 1e-6;
94   double step = (hi - lo)/255.0;
95   table->SetTableRange(lo,hi);
96   table->Build();
97   TestAssert(table->GetIndex(lo) == 0);
98   TestAssert(table->GetIndex(hi) == 255);
99   TestAssert(table->GetIndex(lo+tol) == 0);
100   TestAssert(table->GetIndex(hi-tol) == 255);
101   TestAssert(table->GetIndex(lo-step) == 0);
102   TestAssert(table->GetIndex(hi+step) == 255);
103   TestAssert(table->GetIndex(lo+step) == 1);
104   TestAssert(table->GetIndex(hi-step) == 254);
105   TestAssert(table->GetIndex(vtkMath::Nan()) == -1);
106 
107   double rgba[4];
108   rgba[0] = 0.0;  rgba[1] = 0.0;  rgba[2] = 0.0;  rgba[3] = 1.0;
109   TestVector4d(table->GetBelowRangeColor(), rgba);
110   rgba[0] = 1.0;  rgba[1] = 1.0;  rgba[2] = 1.0;  rgba[3] = 1.0;
111   TestVector4d(table->GetAboveRangeColor(), rgba);
112 
113   TestAssert(table->GetUseBelowRangeColor() == 0);
114   TestAssert(table->GetUseAboveRangeColor() == 0);
115 
116   unsigned char expected[4];
117 
118   // Test handling of below-range colors
119   vtkMath::HSVToRGB(table->GetHueRange()[0],
120                     table->GetSaturationRange()[0],
121                     table->GetValueRange()[0],
122                     &rgba[0], &rgba[1], &rgba[2]);
123   rgba[3] = table->GetAlphaRange()[0];
124 
125   vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
126   table->UseBelowRangeColorOff();
127   table->Build();
128   const unsigned char *result = table->MapValue(lo);
129   TestAssert(TestColor4uc(expected, result));
130 
131   table->GetBelowRangeColor(rgba);
132   vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
133   table->UseBelowRangeColorOn();
134   table->Build();
135   result = table->MapValue(lo-tol);
136   TestAssert(TestColor4uc(expected, result));
137 
138   // Test handling of above-range colors
139   vtkMath::HSVToRGB(table->GetHueRange()[1],
140                     table->GetSaturationRange()[1],
141                     table->GetValueRange()[1],
142                     &rgba[0], &rgba[1], &rgba[2]);
143   rgba[3] = table->GetAlphaRange()[1];
144 
145   vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
146   table->UseAboveRangeColorOff();
147   table->Build();
148   result = table->MapValue(hi);
149   TestAssert(TestColor4uc(expected, result));
150 
151   table->GetAboveRangeColor(rgba);
152   vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
153   table->UseAboveRangeColorOn();
154   table->Build();
155   result = table->MapValue(hi+tol);
156   TestAssert(TestColor4uc(expected, result));
157 
158   // log range test
159   lo = pow(10.0,lo);
160   hi = pow(10.0,hi);
161   step = pow(10.0,step);
162   table->SetScaleToLog10();
163   table->SetTableRange(lo,hi);
164   table->Build();
165   TestAssert(table->GetIndex(lo) == 0);
166   TestAssert(table->GetIndex(hi) == 255);
167   TestAssert(table->GetIndex(lo+tol) == 0);
168   TestAssert(table->GetIndex(hi-tol) == 255);
169   TestAssert(table->GetIndex(vtkMath::Nan()) == -1);
170 
171   // Note - both below- and above-range colors are enabled at this point
172   TestAssert(table->GetIndex(lo/step) == 0);
173   TestAssert(table->GetIndex(hi*step) == 255);
174   TestAssert(table->GetIndex(lo*step) == 1);
175   TestAssert(table->GetIndex(hi/step) == 254);
176 
177   // negative log range
178   double tmp = hi;
179   hi = -lo;
180   lo = -tmp;
181   step = 1.0/step;
182   table->SetScaleToLog10();
183   table->SetTableRange(lo,hi);
184   table->Build();
185   TestAssert(table->GetIndex(lo) == 0);
186   TestAssert(table->GetIndex(hi) == 255);
187   TestAssert(table->GetIndex(lo+tol) == 0);
188   TestAssert(table->GetIndex(hi-tol) == 255);
189   TestAssert(table->GetIndex(lo/step) == 0);
190   TestAssert(table->GetIndex(hi*step) == 255);
191   TestAssert(table->GetIndex(lo*step) == 1);
192   TestAssert(table->GetIndex(hi/step) == 254);
193 
194   // == check error reporting ==
195 
196   errorObserver observer;
197   unsigned long observerId =
198     table->AddObserver(
199       vtkCommand::ErrorEvent, &observer, &errorObserver::Callback);
200 
201   // linear table, range is null, permitted (step function)
202   observer.Reset();
203   table->SetScaleToLinear();
204   table->SetTableRange(0,0);
205   TestAssert(observer.GetEvent() == 0);
206 
207   // linear table, range is inverted, illegal
208   observer.Reset();
209   table->SetScaleToLinear();
210   table->SetTableRange(1,-1);
211   TestAssert(observer.GetEvent() != 0);
212 
213   // log table, range is null, permitted (step function)
214   observer.Reset();
215   table->SetScaleToLog10();
216   table->SetTableRange(0,0);
217   TestAssert(observer.GetEvent() == 0);
218 
219   // log table, zero on upper end of range, permitted
220   observer.Reset();
221   table->SetScaleToLog10();
222   table->SetTableRange(-1.2,0);
223   TestAssert(observer.GetEvent() == 0);
224 
225   // log table, zero on lower end of range, permitted
226   observer.Reset();
227   table->SetScaleToLog10();
228   table->SetTableRange(0,1.3);
229   TestAssert(observer.GetEvent() == 0);
230 
231   // log table, range straddles zero, illegal
232   observer.Reset();
233   table->SetScaleToLog10();
234   table->SetTableRange(-0.5,1.1);
235   TestAssert(observer.GetEvent() != 0);
236 
237   table->RemoveObserver(observerId);
238 
239   return rval;
240 }
241