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(unsigned char * expected,unsigned char * test)39 int TestColor4uc(unsigned char* expected, 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], *result;
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   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 
170   // Note - both below- and above-range colors are enabled at this point
171   TestAssert(table->GetIndex(lo/step) == 0);
172   TestAssert(table->GetIndex(hi*step) == 255);
173   TestAssert(table->GetIndex(lo*step) == 1);
174   TestAssert(table->GetIndex(hi/step) == 254);
175 
176   // negative log range
177   double tmp = hi;
178   hi = -lo;
179   lo = -tmp;
180   step = 1.0/step;
181   table->SetScaleToLog10();
182   table->SetTableRange(lo,hi);
183   table->Build();
184   TestAssert(table->GetIndex(lo) == 0);
185   TestAssert(table->GetIndex(hi) == 255);
186   TestAssert(table->GetIndex(lo+tol) == 0);
187   TestAssert(table->GetIndex(hi-tol) == 255);
188   TestAssert(table->GetIndex(lo/step) == 0);
189   TestAssert(table->GetIndex(hi*step) == 255);
190   TestAssert(table->GetIndex(lo*step) == 1);
191   TestAssert(table->GetIndex(hi/step) == 254);
192 
193   // == check error reporting ==
194 
195   errorObserver observer;
196   unsigned long observerId =
197     table->AddObserver(
198       vtkCommand::ErrorEvent, &observer, &errorObserver::Callback);
199 
200   // linear table, range is null, permitted (step function)
201   observer.Reset();
202   table->SetScaleToLinear();
203   table->SetTableRange(0,0);
204   TestAssert(observer.GetEvent() == 0);
205 
206   // linear table, range is inverted, illegal
207   observer.Reset();
208   table->SetScaleToLinear();
209   table->SetTableRange(1,-1);
210   TestAssert(observer.GetEvent() != 0);
211 
212   // log table, range is null, permitted (step function)
213   observer.Reset();
214   table->SetScaleToLog10();
215   table->SetTableRange(0,0);
216   TestAssert(observer.GetEvent() == 0);
217 
218   // log table, zero on upper end of range, permitted
219   observer.Reset();
220   table->SetScaleToLog10();
221   table->SetTableRange(-1.2,0);
222   TestAssert(observer.GetEvent() == 0);
223 
224   // log table, zero on lower end of range, permitted
225   observer.Reset();
226   table->SetScaleToLog10();
227   table->SetTableRange(0,1.3);
228   TestAssert(observer.GetEvent() == 0);
229 
230   // log table, range straddles zero, illegal
231   observer.Reset();
232   table->SetScaleToLog10();
233   table->SetTableRange(-0.5,1.1);
234   TestAssert(observer.GetEvent() != 0);
235 
236   table->RemoveObserver(observerId);
237 
238   return rval;
239 }
240